1e37f8451SRapkiewicz, Pawel /* 2e37f8451SRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation 3e37f8451SRapkiewicz, Pawel // 4e37f8451SRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License"); 5e37f8451SRapkiewicz, Pawel // you may not use this file except in compliance with the License. 6e37f8451SRapkiewicz, Pawel // You may obtain a copy of the License at 7e37f8451SRapkiewicz, Pawel // 8e37f8451SRapkiewicz, Pawel // http://www.apache.org/licenses/LICENSE-2.0 9e37f8451SRapkiewicz, Pawel // 10e37f8451SRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software 11e37f8451SRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS, 12e37f8451SRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e37f8451SRapkiewicz, Pawel // See the License for the specific language governing permissions and 14e37f8451SRapkiewicz, Pawel // limitations under the License. 15e37f8451SRapkiewicz, Pawel */ 16e37f8451SRapkiewicz, Pawel #pragma once 17e37f8451SRapkiewicz, Pawel 1813451e39SWilly Tu #include "bmcweb_config.h" 1913451e39SWilly Tu 203ccb3adbSEd Tanous #include "app.hpp" 217a1dbc48SGeorge Liu #include "dbus_utility.hpp" 22b49ac873SJames Feist #include "health.hpp" 231c8fba97SJames Feist #include "led.hpp" 243ccb3adbSEd Tanous #include "query.hpp" 253ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 263ccb3adbSEd Tanous #include "utils/collection.hpp" 273ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 28cf7eba09SNan Zhou #include "utils/json_utils.hpp" 291abe55efSEd Tanous 30e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 31ef4c65b7SEd Tanous #include <boost/url/format.hpp> 321e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp> 33fc903b3dSAndrew Geissler #include <sdbusplus/message.hpp> 3486d89ed7SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 351214b7e7SGunnar Mills 367a1dbc48SGeorge Liu #include <array> 377a1dbc48SGeorge Liu #include <string_view> 387a1dbc48SGeorge Liu 391abe55efSEd Tanous namespace redfish 401abe55efSEd Tanous { 41e37f8451SRapkiewicz, Pawel 42e37f8451SRapkiewicz, Pawel /** 435e577bc1SWilly Tu * @brief Retrieves resources over dbus to link to the chassis 445e577bc1SWilly Tu * 455e577bc1SWilly Tu * @param[in] asyncResp - Shared pointer for completing asynchronous 465e577bc1SWilly Tu * calls 475e577bc1SWilly Tu * @param[in] path - Chassis dbus path to look for the storage. 485e577bc1SWilly Tu * 495e577bc1SWilly Tu * Calls the Association endpoints on the path + "/storage" and add the link of 505e577bc1SWilly Tu * json["Links"]["Storage@odata.count"] = 515e577bc1SWilly Tu * {"@odata.id", "/redfish/v1/Storage/" + resourceId} 525e577bc1SWilly Tu * 535e577bc1SWilly Tu * @return None. 545e577bc1SWilly Tu */ 555e577bc1SWilly Tu inline void getStorageLink(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 565e577bc1SWilly Tu const sdbusplus::message::object_path& path) 575e577bc1SWilly Tu { 585e577bc1SWilly Tu sdbusplus::asio::getProperty<std::vector<std::string>>( 595e577bc1SWilly Tu *crow::connections::systemBus, "xyz.openbmc_project.ObjectMapper", 605e577bc1SWilly Tu (path / "storage").str, "xyz.openbmc_project.Association", "endpoints", 61d4b054c1SWilly Tu [asyncResp](const boost::system::error_code& ec, 625e577bc1SWilly Tu const std::vector<std::string>& storageList) { 635e577bc1SWilly Tu if (ec) 645e577bc1SWilly Tu { 655e577bc1SWilly Tu BMCWEB_LOG_DEBUG << "getStorageLink got DBUS response error"; 665e577bc1SWilly Tu return; 675e577bc1SWilly Tu } 685e577bc1SWilly Tu 695e577bc1SWilly Tu nlohmann::json::array_t storages; 705e577bc1SWilly Tu for (const std::string& storagePath : storageList) 715e577bc1SWilly Tu { 725e577bc1SWilly Tu std::string id = 735e577bc1SWilly Tu sdbusplus::message::object_path(storagePath).filename(); 745e577bc1SWilly Tu if (id.empty()) 755e577bc1SWilly Tu { 765e577bc1SWilly Tu continue; 775e577bc1SWilly Tu } 785e577bc1SWilly Tu 795e577bc1SWilly Tu nlohmann::json::object_t storage; 805e577bc1SWilly Tu storage["@odata.id"] = boost::urls::format( 815e577bc1SWilly Tu "/redfish/v1/Systems/system/Storage/{}", id); 825e577bc1SWilly Tu storages.emplace_back(std::move(storage)); 835e577bc1SWilly Tu } 845e577bc1SWilly Tu asyncResp->res.jsonValue["Links"]["Storage@odata.count"] = 855e577bc1SWilly Tu storages.size(); 865e577bc1SWilly Tu asyncResp->res.jsonValue["Links"]["Storage"] = std::move(storages); 875e577bc1SWilly Tu }); 885e577bc1SWilly Tu } 895e577bc1SWilly Tu 905e577bc1SWilly Tu /** 91beeca0aeSGunnar Mills * @brief Retrieves chassis state properties over dbus 92beeca0aeSGunnar Mills * 93ac106bf6SEd Tanous * @param[in] asyncResp - Shared pointer for completing asynchronous calls. 94beeca0aeSGunnar Mills * 95beeca0aeSGunnar Mills * @return None. 96beeca0aeSGunnar Mills */ 97ac106bf6SEd Tanous inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> asyncResp) 98beeca0aeSGunnar Mills { 991e1e598dSJonathan Doman // crow::connections::systemBus->async_method_call( 1001e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 1011e1e598dSJonathan Doman *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis", 1021e1e598dSJonathan Doman "/xyz/openbmc_project/state/chassis0", 1031e1e598dSJonathan Doman "xyz.openbmc_project.State.Chassis", "CurrentPowerState", 104ac106bf6SEd Tanous [asyncResp{std::move(asyncResp)}](const boost::system::error_code& ec, 1051e1e598dSJonathan Doman const std::string& chassisState) { 106beeca0aeSGunnar Mills if (ec) 107beeca0aeSGunnar Mills { 108a6e5e0abSCarson Labrado if (ec == boost::system::errc::host_unreachable) 109a6e5e0abSCarson Labrado { 110a6e5e0abSCarson Labrado // Service not available, no error, just don't return 111a6e5e0abSCarson Labrado // chassis state info 112a6e5e0abSCarson Labrado BMCWEB_LOG_DEBUG << "Service not available " << ec; 113a6e5e0abSCarson Labrado return; 114a6e5e0abSCarson Labrado } 115ac106bf6SEd Tanous BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 116ac106bf6SEd Tanous messages::internalError(asyncResp->res); 117beeca0aeSGunnar Mills return; 118beeca0aeSGunnar Mills } 119beeca0aeSGunnar Mills 1201e1e598dSJonathan Doman BMCWEB_LOG_DEBUG << "Chassis state: " << chassisState; 121beeca0aeSGunnar Mills // Verify Chassis State 122002d39b4SEd Tanous if (chassisState == "xyz.openbmc_project.State.Chassis.PowerState.On") 123beeca0aeSGunnar Mills { 124ac106bf6SEd Tanous asyncResp->res.jsonValue["PowerState"] = "On"; 125ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 126beeca0aeSGunnar Mills } 1271e1e598dSJonathan Doman else if (chassisState == 128beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis.PowerState.Off") 129beeca0aeSGunnar Mills { 130ac106bf6SEd Tanous asyncResp->res.jsonValue["PowerState"] = "Off"; 131ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "StandbyOffline"; 132beeca0aeSGunnar Mills } 1331e1e598dSJonathan Doman }); 134beeca0aeSGunnar Mills } 135beeca0aeSGunnar Mills 136ac106bf6SEd Tanous inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 137c181942fSQiang XU const std::string& service, 138c181942fSQiang XU const std::string& objPath) 139c181942fSQiang XU { 140c181942fSQiang XU BMCWEB_LOG_DEBUG << "Get intrusion status by service \n"; 141c181942fSQiang XU 1421e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 1431e1e598dSJonathan Doman *crow::connections::systemBus, service, objPath, 1441e1e598dSJonathan Doman "xyz.openbmc_project.Chassis.Intrusion", "Status", 145ac106bf6SEd Tanous [asyncResp{std::move(asyncResp)}](const boost::system::error_code& ec, 1461e1e598dSJonathan Doman const std::string& value) { 147c181942fSQiang XU if (ec) 148c181942fSQiang XU { 1494e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 150c181942fSQiang XU // mandatory property 151c181942fSQiang XU BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n"; 152c181942fSQiang XU return; 153c181942fSQiang XU } 154c181942fSQiang XU 155ac106bf6SEd Tanous asyncResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensorNumber"] = 156ac106bf6SEd Tanous 1; 157ac106bf6SEd Tanous asyncResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensor"] = value; 1581e1e598dSJonathan Doman }); 159c181942fSQiang XU } 160c181942fSQiang XU 161c181942fSQiang XU /** 162c181942fSQiang XU * Retrieves physical security properties over dbus 163c181942fSQiang XU */ 164ac106bf6SEd Tanous inline void 165ac106bf6SEd Tanous getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> asyncResp) 166c181942fSQiang XU { 167e99073f5SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 168e99073f5SGeorge Liu "xyz.openbmc_project.Chassis.Intrusion"}; 169e99073f5SGeorge Liu dbus::utility::getSubTree( 170e99073f5SGeorge Liu "/xyz/openbmc_project/Intrusion", 1, interfaces, 171ac106bf6SEd Tanous [asyncResp{std::move(asyncResp)}]( 172e99073f5SGeorge Liu const boost::system::error_code& ec, 173b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 174c181942fSQiang XU if (ec) 175c181942fSQiang XU { 1764e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 177c181942fSQiang XU // mandatory property 178002d39b4SEd Tanous BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec << "\n"; 179c181942fSQiang XU return; 180c181942fSQiang XU } 181c181942fSQiang XU // Iterate over all retrieved ObjectPaths. 182c181942fSQiang XU for (const auto& object : subtree) 183c181942fSQiang XU { 184840a9ffcSPatrick Williams if (!object.second.empty()) 185c181942fSQiang XU { 186840a9ffcSPatrick Williams const auto service = object.second.front(); 187ac106bf6SEd Tanous getIntrusionByService(asyncResp, service.first, object.first); 188c181942fSQiang XU return; 189c181942fSQiang XU } 190c181942fSQiang XU } 191e99073f5SGeorge Liu }); 192c181942fSQiang XU } 193c181942fSQiang XU 194cf7eba09SNan Zhou inline void handleChassisCollectionGet( 195cf7eba09SNan Zhou App& app, const crow::Request& req, 196cf7eba09SNan Zhou const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1971abe55efSEd Tanous { 1983ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 19945ca1b86SEd Tanous { 20045ca1b86SEd Tanous return; 20145ca1b86SEd Tanous } 2028d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 2038d1b46d7Szhanghch05 "#ChassisCollection.ChassisCollection"; 2048d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 2058d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 206e37f8451SRapkiewicz, Pawel 2077a1dbc48SGeorge Liu constexpr std::array<std::string_view, 2> interfaces{ 2087a1dbc48SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board", 2097a1dbc48SGeorge Liu "xyz.openbmc_project.Inventory.Item.Chassis"}; 21002f6ff19SGunnar Mills collection_util::getCollectionMembers( 2117a1dbc48SGeorge Liu asyncResp, boost::urls::url("/redfish/v1/Chassis"), interfaces); 212cf7eba09SNan Zhou } 213cf7eba09SNan Zhou 214cf7eba09SNan Zhou /** 215cf7eba09SNan Zhou * ChassisCollection derived class for delivering Chassis Collection Schema 216cf7eba09SNan Zhou * Functions triggers appropriate requests on DBus 217cf7eba09SNan Zhou */ 218cf7eba09SNan Zhou inline void requestRoutesChassisCollection(App& app) 219cf7eba09SNan Zhou { 220cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/") 221cf7eba09SNan Zhou .privileges(redfish::privileges::getChassisCollection) 222cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 223cf7eba09SNan Zhou std::bind_front(handleChassisCollectionGet, std::ref(app))); 22462d5e2e4SEd Tanous } 225e37f8451SRapkiewicz, Pawel 226308f70c7SWilly Tu inline void 227308f70c7SWilly Tu getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 228308f70c7SWilly Tu const std::string& connectionName, 229308f70c7SWilly Tu const std::string& path) 230308f70c7SWilly Tu { 2311e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 2321e1e598dSJonathan Doman *crow::connections::systemBus, connectionName, path, 2331e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 2345e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec, 2351e1e598dSJonathan Doman const std::string& property) { 236308f70c7SWilly Tu if (ec) 237308f70c7SWilly Tu { 23851dab2a7SAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error for Location"; 239308f70c7SWilly Tu messages::internalError(asyncResp->res); 240308f70c7SWilly Tu return; 241308f70c7SWilly Tu } 242308f70c7SWilly Tu 243002d39b4SEd Tanous asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 2441e1e598dSJonathan Doman property; 2451e1e598dSJonathan Doman }); 246308f70c7SWilly Tu } 247308f70c7SWilly Tu 248308f70c7SWilly Tu inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 249308f70c7SWilly Tu const std::string& connectionName, 250308f70c7SWilly Tu const std::string& path) 251308f70c7SWilly Tu { 2521e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 2531e1e598dSJonathan Doman *crow::connections::systemBus, connectionName, path, 2541e1e598dSJonathan Doman "xyz.openbmc_project.Common.UUID", "UUID", 2555e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec, 2561e1e598dSJonathan Doman const std::string& chassisUUID) { 257308f70c7SWilly Tu if (ec) 258308f70c7SWilly Tu { 25951dab2a7SAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error for UUID"; 260308f70c7SWilly Tu messages::internalError(asyncResp->res); 261308f70c7SWilly Tu return; 262308f70c7SWilly Tu } 2631e1e598dSJonathan Doman asyncResp->res.jsonValue["UUID"] = chassisUUID; 2641e1e598dSJonathan Doman }); 265308f70c7SWilly Tu } 266308f70c7SWilly Tu 267cf7eba09SNan Zhou inline void 268cf7eba09SNan Zhou handleChassisGet(App& app, const crow::Request& req, 26945ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 270cf7eba09SNan Zhou const std::string& chassisId) 271cf7eba09SNan Zhou { 2723ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 27345ca1b86SEd Tanous { 27445ca1b86SEd Tanous return; 27545ca1b86SEd Tanous } 276e99073f5SGeorge Liu constexpr std::array<std::string_view, 2> interfaces = { 277734bfe90SGunnar Mills "xyz.openbmc_project.Inventory.Item.Board", 278adc4f0dbSShawn McCarney "xyz.openbmc_project.Inventory.Item.Chassis"}; 279734bfe90SGunnar Mills 280e99073f5SGeorge Liu dbus::utility::getSubTree( 281e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 28262d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 283e99073f5SGeorge Liu const boost::system::error_code& ec, 284b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 28562d5e2e4SEd Tanous if (ec) 2861abe55efSEd Tanous { 28751dab2a7SAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 288f12894f8SJason M. Bills messages::internalError(asyncResp->res); 289daf36e2eSEd Tanous return; 290daf36e2eSEd Tanous } 291daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 292cf7eba09SNan Zhou for (const std::pair< 293cf7eba09SNan Zhou std::string, 294cf7eba09SNan Zhou std::vector<std::pair<std::string, std::vector<std::string>>>>& 2951214b7e7SGunnar Mills object : subtree) 2961abe55efSEd Tanous { 297daf36e2eSEd Tanous const std::string& path = object.first; 298cf7eba09SNan Zhou const std::vector<std::pair<std::string, std::vector<std::string>>>& 2991214b7e7SGunnar Mills connectionNames = object.second; 3007e860f15SJohn Edward Broadbent 301997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 302997093ebSGeorge Liu if (objPath.filename() != chassisId) 3031abe55efSEd Tanous { 304daf36e2eSEd Tanous continue; 305daf36e2eSEd Tanous } 30626f03899SShawn McCarney 307002d39b4SEd Tanous auto health = std::make_shared<HealthPopulate>(asyncResp); 308b49ac873SJames Feist 30913451e39SWilly Tu if constexpr (bmcwebEnableHealthPopulate) 31013451e39SWilly Tu { 3116c3e9451SGeorge Liu dbus::utility::getAssociationEndPoints( 3126c3e9451SGeorge Liu path + "/all_sensors", 3135e7e2dc5SEd Tanous [health](const boost::system::error_code& ec2, 3146c3e9451SGeorge Liu const dbus::utility::MapperEndPoints& resp) { 31523a21a1cSEd Tanous if (ec2) 316b49ac873SJames Feist { 317b49ac873SJames Feist return; // no sensors = no failures 318b49ac873SJames Feist } 3191e1e598dSJonathan Doman health->inventory = resp; 3201e1e598dSJonathan Doman }); 321b49ac873SJames Feist 322b49ac873SJames Feist health->populate(); 32313451e39SWilly Tu } 324b49ac873SJames Feist 32526f6976fSEd Tanous if (connectionNames.empty()) 3261abe55efSEd Tanous { 3271c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 328e0d918bcSEd Tanous continue; 329daf36e2eSEd Tanous } 330e0d918bcSEd Tanous 33149c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.type"] = 332523d4868SLogananth Sundararaj "#Chassis.v1_22_0.Chassis"; 33349c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.id"] = 334ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", chassisId); 33549c53ac9SJohnathan Mantey asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 33649c53ac9SJohnathan Mantey asyncResp->res.jsonValue["ChassisType"] = "RackMount"; 337cf7eba09SNan Zhou asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]["target"] = 338ef4c65b7SEd Tanous boost::urls::format( 339ef4c65b7SEd Tanous "/redfish/v1/Chassis/{}/Actions/Chassis.Reset", chassisId); 3401476687dSEd Tanous asyncResp->res 341cf7eba09SNan Zhou .jsonValue["Actions"]["#Chassis.Reset"]["@Redfish.ActionInfo"] = 342ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}/ResetActionInfo", 343ef4c65b7SEd Tanous chassisId); 3441476687dSEd Tanous asyncResp->res.jsonValue["PCIeDevices"]["@odata.id"] = 345ef4c65b7SEd Tanous "/redfish/v1/Systems/system/PCIeDevices"; 34649c53ac9SJohnathan Mantey 3476c3e9451SGeorge Liu dbus::utility::getAssociationEndPoints( 3486c3e9451SGeorge Liu path + "/drive", 3496c3e9451SGeorge Liu [asyncResp, 3506c3e9451SGeorge Liu chassisId](const boost::system::error_code& ec3, 3516c3e9451SGeorge Liu const dbus::utility::MapperEndPoints& resp) { 35292903bd4SJohn Edward Broadbent if (ec3 || resp.empty()) 35392903bd4SJohn Edward Broadbent { 35492903bd4SJohn Edward Broadbent return; // no drives = no failures 35592903bd4SJohn Edward Broadbent } 35692903bd4SJohn Edward Broadbent 35792903bd4SJohn Edward Broadbent nlohmann::json reference; 358ef4c65b7SEd Tanous reference["@odata.id"] = boost::urls::format( 359ef4c65b7SEd Tanous "/redfish/v1/Chassis/{}/Drives", chassisId); 36092903bd4SJohn Edward Broadbent asyncResp->res.jsonValue["Drives"] = std::move(reference); 36192903bd4SJohn Edward Broadbent }); 36292903bd4SJohn Edward Broadbent 363002d39b4SEd Tanous const std::string& connectionName = connectionNames[0].first; 3641c8fba97SJames Feist 36523a21a1cSEd Tanous const std::vector<std::string>& interfaces2 = 3661c8fba97SJames Feist connectionNames[0].second; 3671c8fba97SJames Feist const std::array<const char*, 2> hasIndicatorLed = { 3681c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 3690fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 3701c8fba97SJames Feist 371476b9cc5STejas Patil const std::string assetTagInterface = 3720fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.AssetTag"; 373523d4868SLogananth Sundararaj const std::string replaceableInterface = 374523d4868SLogananth Sundararaj "xyz.openbmc_project.Inventory.Decorator.Replaceable"; 375523d4868SLogananth Sundararaj for (const auto& interface : interfaces2) 376523d4868SLogananth Sundararaj { 377523d4868SLogananth Sundararaj if (interface == assetTagInterface) 378476b9cc5STejas Patil { 3791e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 380002d39b4SEd Tanous *crow::connections::systemBus, connectionName, path, 381002d39b4SEd Tanous assetTagInterface, "AssetTag", 382523d4868SLogananth Sundararaj [asyncResp, 383523d4868SLogananth Sundararaj chassisId](const boost::system::error_code& ec2, 3841e1e598dSJonathan Doman const std::string& property) { 3858a592810SEd Tanous if (ec2) 386476b9cc5STejas Patil { 387523d4868SLogananth Sundararaj BMCWEB_LOG_ERROR 388523d4868SLogananth Sundararaj << "DBus response error for AssetTag: " << ec2; 389476b9cc5STejas Patil messages::internalError(asyncResp->res); 390476b9cc5STejas Patil return; 391476b9cc5STejas Patil } 392002d39b4SEd Tanous asyncResp->res.jsonValue["AssetTag"] = property; 3931e1e598dSJonathan Doman }); 394476b9cc5STejas Patil } 395523d4868SLogananth Sundararaj else if (interface == replaceableInterface) 396523d4868SLogananth Sundararaj { 397523d4868SLogananth Sundararaj sdbusplus::asio::getProperty<bool>( 398523d4868SLogananth Sundararaj *crow::connections::systemBus, connectionName, path, 399523d4868SLogananth Sundararaj replaceableInterface, "HotPluggable", 400523d4868SLogananth Sundararaj [asyncResp, 401523d4868SLogananth Sundararaj chassisId](const boost::system::error_code& ec2, 402523d4868SLogananth Sundararaj const bool property) { 403523d4868SLogananth Sundararaj if (ec2) 404523d4868SLogananth Sundararaj { 405523d4868SLogananth Sundararaj BMCWEB_LOG_ERROR 406523d4868SLogananth Sundararaj << "DBus response error for HotPluggable: " 407523d4868SLogananth Sundararaj << ec2; 408523d4868SLogananth Sundararaj messages::internalError(asyncResp->res); 409523d4868SLogananth Sundararaj return; 410523d4868SLogananth Sundararaj } 411523d4868SLogananth Sundararaj asyncResp->res.jsonValue["HotPluggable"] = property; 412523d4868SLogananth Sundararaj }); 413523d4868SLogananth Sundararaj } 414523d4868SLogananth Sundararaj } 415476b9cc5STejas Patil 4161c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 4171c8fba97SJames Feist { 418002d39b4SEd Tanous if (std::find(interfaces2.begin(), interfaces2.end(), 41923a21a1cSEd Tanous interface) != interfaces2.end()) 4201c8fba97SJames Feist { 4211c8fba97SJames Feist getIndicatorLedState(asyncResp); 4229f8bfa7cSGunnar Mills getLocationIndicatorActive(asyncResp); 4231c8fba97SJames Feist break; 4241c8fba97SJames Feist } 4251c8fba97SJames Feist } 4261c8fba97SJames Feist 42786d89ed7SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 42886d89ed7SKrzysztof Grobelny *crow::connections::systemBus, connectionName, path, 42986d89ed7SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Decorator.Asset", 4305e577bc1SWilly Tu [asyncResp, chassisId(std::string(chassisId)), 4315e577bc1SWilly Tu path](const boost::system::error_code& /*ec2*/, 432cf7eba09SNan Zhou const dbus::utility::DBusPropertiesMap& propertiesList) { 43386d89ed7SKrzysztof Grobelny const std::string* partNumber = nullptr; 43486d89ed7SKrzysztof Grobelny const std::string* serialNumber = nullptr; 43586d89ed7SKrzysztof Grobelny const std::string* manufacturer = nullptr; 43686d89ed7SKrzysztof Grobelny const std::string* model = nullptr; 43786d89ed7SKrzysztof Grobelny const std::string* sparePartNumber = nullptr; 43886d89ed7SKrzysztof Grobelny 43986d89ed7SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 44086d89ed7SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), propertiesList, 44186d89ed7SKrzysztof Grobelny "PartNumber", partNumber, "SerialNumber", serialNumber, 44286d89ed7SKrzysztof Grobelny "Manufacturer", manufacturer, "Model", model, 44386d89ed7SKrzysztof Grobelny "SparePartNumber", sparePartNumber); 44486d89ed7SKrzysztof Grobelny 44586d89ed7SKrzysztof Grobelny if (!success) 4461abe55efSEd Tanous { 447002d39b4SEd Tanous messages::internalError(asyncResp->res); 448caa11f7aSAlpana Kumari return; 449daf36e2eSEd Tanous } 45086d89ed7SKrzysztof Grobelny 45186d89ed7SKrzysztof Grobelny if (partNumber != nullptr) 45286d89ed7SKrzysztof Grobelny { 45386d89ed7SKrzysztof Grobelny asyncResp->res.jsonValue["PartNumber"] = *partNumber; 45486d89ed7SKrzysztof Grobelny } 45586d89ed7SKrzysztof Grobelny 45686d89ed7SKrzysztof Grobelny if (serialNumber != nullptr) 45786d89ed7SKrzysztof Grobelny { 45886d89ed7SKrzysztof Grobelny asyncResp->res.jsonValue["SerialNumber"] = *serialNumber; 45986d89ed7SKrzysztof Grobelny } 46086d89ed7SKrzysztof Grobelny 46186d89ed7SKrzysztof Grobelny if (manufacturer != nullptr) 46286d89ed7SKrzysztof Grobelny { 46386d89ed7SKrzysztof Grobelny asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 46486d89ed7SKrzysztof Grobelny } 46586d89ed7SKrzysztof Grobelny 46686d89ed7SKrzysztof Grobelny if (model != nullptr) 46786d89ed7SKrzysztof Grobelny { 46886d89ed7SKrzysztof Grobelny asyncResp->res.jsonValue["Model"] = *model; 46986d89ed7SKrzysztof Grobelny } 47086d89ed7SKrzysztof Grobelny 471caa11f7aSAlpana Kumari // SparePartNumber is optional on D-Bus 472caa11f7aSAlpana Kumari // so skip if it is empty 47386d89ed7SKrzysztof Grobelny if (sparePartNumber != nullptr && !sparePartNumber->empty()) 474caa11f7aSAlpana Kumari { 47586d89ed7SKrzysztof Grobelny asyncResp->res.jsonValue["SparePartNumber"] = 47686d89ed7SKrzysztof Grobelny *sparePartNumber; 477caa11f7aSAlpana Kumari } 47886d89ed7SKrzysztof Grobelny 47962d5e2e4SEd Tanous asyncResp->res.jsonValue["Name"] = chassisId; 48062d5e2e4SEd Tanous asyncResp->res.jsonValue["Id"] = chassisId; 4810256b694Szhanghch05 #ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL 482002d39b4SEd Tanous asyncResp->res.jsonValue["Thermal"]["@odata.id"] = 483ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}/Thermal", 484ef4c65b7SEd Tanous chassisId); 4852474adfaSEd Tanous // Power object 4861476687dSEd Tanous asyncResp->res.jsonValue["Power"]["@odata.id"] = 487ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}/Power", 488ef4c65b7SEd Tanous chassisId); 4890256b694Szhanghch05 #endif 4902973963eSXiaochao Ma #ifdef BMCWEB_NEW_POWERSUBSYSTEM_THERMALSUBSYSTEM 4912973963eSXiaochao Ma asyncResp->res.jsonValue["ThermalSubsystem"]["@odata.id"] = 492ef4c65b7SEd Tanous boost::urls::format( 493ef4c65b7SEd Tanous "/redfish/v1/Chassis/{}/ThermalSubsystem", chassisId); 49477b36437SChicago Duan asyncResp->res.jsonValue["PowerSubsystem"]["@odata.id"] = 495ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}/PowerSubsystem", 496ef4c65b7SEd Tanous chassisId); 4974ca3ec3cSAlbert Zhang asyncResp->res.jsonValue["EnvironmentMetrics"]["@odata.id"] = 498ef4c65b7SEd Tanous boost::urls::format( 499ef4c65b7SEd Tanous "/redfish/v1/Chassis/{}/EnvironmentMetrics", chassisId); 5002973963eSXiaochao Ma #endif 50195a3ecadSAnthony Wilson // SensorCollection 502002d39b4SEd Tanous asyncResp->res.jsonValue["Sensors"]["@odata.id"] = 503ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}/Sensors", 504ef4c65b7SEd Tanous chassisId); 505002d39b4SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 5061476687dSEd Tanous 5071476687dSEd Tanous nlohmann::json::array_t computerSystems; 5081476687dSEd Tanous nlohmann::json::object_t system; 509002d39b4SEd Tanous system["@odata.id"] = "/redfish/v1/Systems/system"; 510ad539545SPatrick Williams computerSystems.emplace_back(std::move(system)); 511002d39b4SEd Tanous asyncResp->res.jsonValue["Links"]["ComputerSystems"] = 5121476687dSEd Tanous std::move(computerSystems); 5131476687dSEd Tanous 5141476687dSEd Tanous nlohmann::json::array_t managedBy; 5151476687dSEd Tanous nlohmann::json::object_t manager; 516002d39b4SEd Tanous manager["@odata.id"] = "/redfish/v1/Managers/bmc"; 517ad539545SPatrick Williams managedBy.emplace_back(std::move(manager)); 5187e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Links"]["ManagedBy"] = 5191476687dSEd Tanous std::move(managedBy); 520beeca0aeSGunnar Mills getChassisState(asyncResp); 5215e577bc1SWilly Tu getStorageLink(asyncResp, path); 52286d89ed7SKrzysztof Grobelny }); 5232c37b4b0SSharad Yadav 524308f70c7SWilly Tu for (const auto& interface : interfaces2) 5252c37b4b0SSharad Yadav { 526308f70c7SWilly Tu if (interface == "xyz.openbmc_project.Common.UUID") 5272c37b4b0SSharad Yadav { 528308f70c7SWilly Tu getChassisUUID(asyncResp, connectionName, path); 5292c37b4b0SSharad Yadav } 530cf7eba09SNan Zhou else if (interface == 5310fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 5322c37b4b0SSharad Yadav { 533002d39b4SEd Tanous getChassisLocationCode(asyncResp, connectionName, path); 5342c37b4b0SSharad Yadav } 5352c37b4b0SSharad Yadav } 5362c37b4b0SSharad Yadav 537daf36e2eSEd Tanous return; 538daf36e2eSEd Tanous } 539e0d918bcSEd Tanous 540daf36e2eSEd Tanous // Couldn't find an object with that name. return an error 541d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 542e99073f5SGeorge Liu }); 543c181942fSQiang XU 544c181942fSQiang XU getPhysicalSecurityData(asyncResp); 545cf7eba09SNan Zhou } 5461c8fba97SJames Feist 547cf7eba09SNan Zhou inline void 548cf7eba09SNan Zhou handleChassisPatch(App& app, const crow::Request& req, 5497e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 550cf7eba09SNan Zhou const std::string& param) 551cf7eba09SNan Zhou { 5523ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 55345ca1b86SEd Tanous { 55445ca1b86SEd Tanous return; 55545ca1b86SEd Tanous } 5569f8bfa7cSGunnar Mills std::optional<bool> locationIndicatorActive; 5571c8fba97SJames Feist std::optional<std::string> indicatorLed; 5581c8fba97SJames Feist 5597e860f15SJohn Edward Broadbent if (param.empty()) 5601c8fba97SJames Feist { 5611c8fba97SJames Feist return; 5621c8fba97SJames Feist } 5631c8fba97SJames Feist 56415ed6780SWilly Tu if (!json_util::readJsonPatch( 5657e860f15SJohn Edward Broadbent req, asyncResp->res, "LocationIndicatorActive", 5667e860f15SJohn Edward Broadbent locationIndicatorActive, "IndicatorLED", indicatorLed)) 5671c8fba97SJames Feist { 5681c8fba97SJames Feist return; 5691c8fba97SJames Feist } 5701c8fba97SJames Feist 5719f8bfa7cSGunnar Mills // TODO (Gunnar): Remove IndicatorLED after enough time has passed 5729f8bfa7cSGunnar Mills if (!locationIndicatorActive && !indicatorLed) 5731c8fba97SJames Feist { 5741c8fba97SJames Feist return; // delete this when we support more patch properties 5751c8fba97SJames Feist } 576d6aa0093SGunnar Mills if (indicatorLed) 577d6aa0093SGunnar Mills { 5787e860f15SJohn Edward Broadbent asyncResp->res.addHeader( 5797e860f15SJohn Edward Broadbent boost::beast::http::field::warning, 5800fda0f12SGeorge Liu "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\""); 581d6aa0093SGunnar Mills } 5821c8fba97SJames Feist 583e99073f5SGeorge Liu constexpr std::array<std::string_view, 2> interfaces = { 5841c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board", 5851c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Chassis"}; 5861c8fba97SJames Feist 5877e860f15SJohn Edward Broadbent const std::string& chassisId = param; 5881c8fba97SJames Feist 589e99073f5SGeorge Liu dbus::utility::getSubTree( 590e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 591cf7eba09SNan Zhou [asyncResp, chassisId, locationIndicatorActive, 5925e7e2dc5SEd Tanous indicatorLed](const boost::system::error_code& ec, 593b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 5941c8fba97SJames Feist if (ec) 5951c8fba97SJames Feist { 59651dab2a7SAndrew Geissler BMCWEB_LOG_ERROR << "DBUS response error " << ec; 5971c8fba97SJames Feist messages::internalError(asyncResp->res); 5981c8fba97SJames Feist return; 5991c8fba97SJames Feist } 6001c8fba97SJames Feist 6011c8fba97SJames Feist // Iterate over all retrieved ObjectPaths. 602cf7eba09SNan Zhou for (const std::pair< 603cf7eba09SNan Zhou std::string, 604cf7eba09SNan Zhou std::vector<std::pair<std::string, std::vector<std::string>>>>& 6051214b7e7SGunnar Mills object : subtree) 6061c8fba97SJames Feist { 6071c8fba97SJames Feist const std::string& path = object.first; 608cf7eba09SNan Zhou const std::vector<std::pair<std::string, std::vector<std::string>>>& 6091214b7e7SGunnar Mills connectionNames = object.second; 6101c8fba97SJames Feist 611997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 612997093ebSGeorge Liu if (objPath.filename() != chassisId) 6131c8fba97SJames Feist { 6141c8fba97SJames Feist continue; 6151c8fba97SJames Feist } 6161c8fba97SJames Feist 61726f6976fSEd Tanous if (connectionNames.empty()) 6181c8fba97SJames Feist { 6191c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 6201c8fba97SJames Feist continue; 6211c8fba97SJames Feist } 6221c8fba97SJames Feist 62323a21a1cSEd Tanous const std::vector<std::string>& interfaces3 = 6241c8fba97SJames Feist connectionNames[0].second; 6251c8fba97SJames Feist 6261c8fba97SJames Feist const std::array<const char*, 2> hasIndicatorLed = { 6271c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 6280fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 6291c8fba97SJames Feist bool indicatorChassis = false; 6301c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 6311c8fba97SJames Feist { 632002d39b4SEd Tanous if (std::find(interfaces3.begin(), interfaces3.end(), 63323a21a1cSEd Tanous interface) != interfaces3.end()) 6341c8fba97SJames Feist { 6351c8fba97SJames Feist indicatorChassis = true; 6361c8fba97SJames Feist break; 6371c8fba97SJames Feist } 6381c8fba97SJames Feist } 6399f8bfa7cSGunnar Mills if (locationIndicatorActive) 6409f8bfa7cSGunnar Mills { 6419f8bfa7cSGunnar Mills if (indicatorChassis) 6429f8bfa7cSGunnar Mills { 643002d39b4SEd Tanous setLocationIndicatorActive(asyncResp, 644002d39b4SEd Tanous *locationIndicatorActive); 6459f8bfa7cSGunnar Mills } 6469f8bfa7cSGunnar Mills else 6479f8bfa7cSGunnar Mills { 648002d39b4SEd Tanous messages::propertyUnknown(asyncResp->res, 649002d39b4SEd Tanous "LocationIndicatorActive"); 6509f8bfa7cSGunnar Mills } 6519f8bfa7cSGunnar Mills } 6529f8bfa7cSGunnar Mills if (indicatorLed) 6539f8bfa7cSGunnar Mills { 6541c8fba97SJames Feist if (indicatorChassis) 6551c8fba97SJames Feist { 656f23b7296SEd Tanous setIndicatorLedState(asyncResp, *indicatorLed); 6571c8fba97SJames Feist } 6581c8fba97SJames Feist else 6591c8fba97SJames Feist { 660cf7eba09SNan Zhou messages::propertyUnknown(asyncResp->res, "IndicatorLED"); 6611c8fba97SJames Feist } 6621c8fba97SJames Feist } 6631c8fba97SJames Feist return; 6641c8fba97SJames Feist } 6651c8fba97SJames Feist 666d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 667e99073f5SGeorge Liu }); 668cf7eba09SNan Zhou } 669cf7eba09SNan Zhou 670cf7eba09SNan Zhou /** 671cf7eba09SNan Zhou * Chassis override class for delivering Chassis Schema 672cf7eba09SNan Zhou * Functions triggers appropriate requests on DBus 673cf7eba09SNan Zhou */ 674cf7eba09SNan Zhou inline void requestRoutesChassis(App& app) 675cf7eba09SNan Zhou { 676cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 677cf7eba09SNan Zhou .privileges(redfish::privileges::getChassis) 678cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 679cf7eba09SNan Zhou std::bind_front(handleChassisGet, std::ref(app))); 680cf7eba09SNan Zhou 681cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 682cf7eba09SNan Zhou .privileges(redfish::privileges::patchChassis) 683cf7eba09SNan Zhou .methods(boost::beast::http::verb::patch)( 684cf7eba09SNan Zhou std::bind_front(handleChassisPatch, std::ref(app))); 6851c8fba97SJames Feist } 686dd99e04bSP.K. Lee 687fc903b3dSAndrew Geissler /** 688fc903b3dSAndrew Geissler * Handle error responses from d-bus for chassis power cycles 689fc903b3dSAndrew Geissler */ 690fc903b3dSAndrew Geissler inline void handleChassisPowerCycleError(const boost::system::error_code& ec, 691fc903b3dSAndrew Geissler const sdbusplus::message_t& eMsg, 692fc903b3dSAndrew Geissler crow::Response& res) 693fc903b3dSAndrew Geissler { 694fc903b3dSAndrew Geissler if (eMsg.get_error() == nullptr) 695fc903b3dSAndrew Geissler { 696fc903b3dSAndrew Geissler BMCWEB_LOG_ERROR << "D-Bus response error: " << ec; 697fc903b3dSAndrew Geissler messages::internalError(res); 698fc903b3dSAndrew Geissler return; 699fc903b3dSAndrew Geissler } 700fc903b3dSAndrew Geissler std::string_view errorMessage = eMsg.get_error()->name; 701fc903b3dSAndrew Geissler 702fc903b3dSAndrew Geissler // If operation failed due to BMC not being in Ready state, tell 703fc903b3dSAndrew Geissler // user to retry in a bit 704fc903b3dSAndrew Geissler if (errorMessage == 705fc903b3dSAndrew Geissler std::string_view("xyz.openbmc_project.State.Chassis.Error.BMCNotReady")) 706fc903b3dSAndrew Geissler { 707fc903b3dSAndrew Geissler BMCWEB_LOG_DEBUG << "BMC not ready, operation not allowed right now"; 708fc903b3dSAndrew Geissler messages::serviceTemporarilyUnavailable(res, "10"); 709fc903b3dSAndrew Geissler return; 710fc903b3dSAndrew Geissler } 711fc903b3dSAndrew Geissler 712fc903b3dSAndrew Geissler BMCWEB_LOG_ERROR << "Chassis Power Cycle fail " << ec 713fc903b3dSAndrew Geissler << " sdbusplus:" << errorMessage; 714fc903b3dSAndrew Geissler messages::internalError(res); 715fc903b3dSAndrew Geissler } 716fc903b3dSAndrew Geissler 7178d1b46d7Szhanghch05 inline void 7188d1b46d7Szhanghch05 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 719dd99e04bSP.K. Lee { 7207a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 721c3b3c92aSVijay Khemka "xyz.openbmc_project.State.Chassis"}; 722c3b3c92aSVijay Khemka 723c3b3c92aSVijay Khemka // Use mapper to get subtree paths. 7247a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 7257a1dbc48SGeorge Liu "/", 0, interfaces, 726b9d36b47SEd Tanous [asyncResp]( 7277a1dbc48SGeorge Liu const boost::system::error_code& ec, 728b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& chassisList) { 729c3b3c92aSVijay Khemka if (ec) 730c3b3c92aSVijay Khemka { 73151dab2a7SAndrew Geissler BMCWEB_LOG_ERROR << "[mapper] Bad D-Bus request error: " << ec; 732c3b3c92aSVijay Khemka messages::internalError(asyncResp->res); 733c3b3c92aSVijay Khemka return; 734c3b3c92aSVijay Khemka } 735c3b3c92aSVijay Khemka 736dd99e04bSP.K. Lee const char* processName = "xyz.openbmc_project.State.Chassis"; 737dd99e04bSP.K. Lee const char* interfaceName = "xyz.openbmc_project.State.Chassis"; 738dd99e04bSP.K. Lee const char* destProperty = "RequestedPowerTransition"; 739dd99e04bSP.K. Lee const std::string propertyValue = 740dd99e04bSP.K. Lee "xyz.openbmc_project.State.Chassis.Transition.PowerCycle"; 741002d39b4SEd Tanous std::string objectPath = "/xyz/openbmc_project/state/chassis_system0"; 742c3b3c92aSVijay Khemka 743c3b3c92aSVijay Khemka /* Look for system reset chassis path */ 744002d39b4SEd Tanous if ((std::find(chassisList.begin(), chassisList.end(), objectPath)) == 745002d39b4SEd Tanous chassisList.end()) 746c3b3c92aSVijay Khemka { 747c3b3c92aSVijay Khemka /* We prefer to reset the full chassis_system, but if it doesn't 748c3b3c92aSVijay Khemka * exist on some platforms, fall back to a host-only power reset 749c3b3c92aSVijay Khemka */ 750c3b3c92aSVijay Khemka objectPath = "/xyz/openbmc_project/state/chassis0"; 751c3b3c92aSVijay Khemka } 752dd99e04bSP.K. Lee 753*9ae226faSGeorge Liu sdbusplus::asio::setProperty( 754*9ae226faSGeorge Liu *crow::connections::systemBus, processName, objectPath, 755*9ae226faSGeorge Liu interfaceName, destProperty, propertyValue, 756fc903b3dSAndrew Geissler [asyncResp](const boost::system::error_code& ec2, 757fc903b3dSAndrew Geissler sdbusplus::message_t& sdbusErrMsg) { 758dd99e04bSP.K. Lee // Use "Set" method to set the property value. 7598a592810SEd Tanous if (ec2) 760dd99e04bSP.K. Lee { 761fc903b3dSAndrew Geissler handleChassisPowerCycleError(ec2, sdbusErrMsg, asyncResp->res); 762fc903b3dSAndrew Geissler 763dd99e04bSP.K. Lee return; 764dd99e04bSP.K. Lee } 765dd99e04bSP.K. Lee 766dd99e04bSP.K. Lee messages::success(asyncResp->res); 767*9ae226faSGeorge Liu }); 7687a1dbc48SGeorge Liu }); 769dd99e04bSP.K. Lee } 770dd99e04bSP.K. Lee 771cf7eba09SNan Zhou inline void handleChassisResetActionInfoPost( 772cf7eba09SNan Zhou App& app, const crow::Request& req, 7737e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 774cf7eba09SNan Zhou const std::string& /*chassisId*/) 775cf7eba09SNan Zhou { 7763ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 77745ca1b86SEd Tanous { 77845ca1b86SEd Tanous return; 77945ca1b86SEd Tanous } 780dd99e04bSP.K. Lee BMCWEB_LOG_DEBUG << "Post Chassis Reset."; 781dd99e04bSP.K. Lee 782dd99e04bSP.K. Lee std::string resetType; 783dd99e04bSP.K. Lee 784cf7eba09SNan Zhou if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType)) 785dd99e04bSP.K. Lee { 786dd99e04bSP.K. Lee return; 787dd99e04bSP.K. Lee } 788dd99e04bSP.K. Lee 789dd99e04bSP.K. Lee if (resetType != "PowerCycle") 790dd99e04bSP.K. Lee { 791dd99e04bSP.K. Lee BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: " 792dd99e04bSP.K. Lee << resetType; 793002d39b4SEd Tanous messages::actionParameterNotSupported(asyncResp->res, resetType, 794002d39b4SEd Tanous "ResetType"); 795dd99e04bSP.K. Lee 796dd99e04bSP.K. Lee return; 797dd99e04bSP.K. Lee } 798dd99e04bSP.K. Lee doChassisPowerCycle(asyncResp); 799dd99e04bSP.K. Lee } 8001cb1a9e6SAppaRao Puli 8011cb1a9e6SAppaRao Puli /** 802cf7eba09SNan Zhou * ChassisResetAction class supports the POST method for the Reset 803cf7eba09SNan Zhou * action. 804cf7eba09SNan Zhou * Function handles POST method request. 805cf7eba09SNan Zhou * Analyzes POST body before sending Reset request data to D-Bus. 8061cb1a9e6SAppaRao Puli */ 807cf7eba09SNan Zhou 808cf7eba09SNan Zhou inline void requestRoutesChassisResetAction(App& app) 8091cb1a9e6SAppaRao Puli { 810cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/") 811cf7eba09SNan Zhou .privileges(redfish::privileges::postChassis) 812cf7eba09SNan Zhou .methods(boost::beast::http::verb::post)( 813cf7eba09SNan Zhou std::bind_front(handleChassisResetActionInfoPost, std::ref(app))); 814cf7eba09SNan Zhou } 815cf7eba09SNan Zhou 816cf7eba09SNan Zhou inline void handleChassisResetActionInfoGet( 817cf7eba09SNan Zhou App& app, const crow::Request& req, 8187e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 819cf7eba09SNan Zhou const std::string& chassisId) 820cf7eba09SNan Zhou { 8213ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 8221cb1a9e6SAppaRao Puli { 82345ca1b86SEd Tanous return; 82445ca1b86SEd Tanous } 825cf7eba09SNan Zhou asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo"; 826ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 827ef4c65b7SEd Tanous "/redfish/v1/Chassis/{}/ResetActionInfo", chassisId); 8281476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 8291476687dSEd Tanous 8301476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 8315b9e95a1SNan Zhou nlohmann::json::array_t parameters; 8325b9e95a1SNan Zhou nlohmann::json::object_t parameter; 8335b9e95a1SNan Zhou parameter["Name"] = "ResetType"; 8345b9e95a1SNan Zhou parameter["Required"] = true; 8355b9e95a1SNan Zhou parameter["DataType"] = "String"; 8361476687dSEd Tanous nlohmann::json::array_t allowed; 837ad539545SPatrick Williams allowed.emplace_back("PowerCycle"); 8385b9e95a1SNan Zhou parameter["AllowableValues"] = std::move(allowed); 839ad539545SPatrick Williams parameters.emplace_back(std::move(parameter)); 8405b9e95a1SNan Zhou 8411476687dSEd Tanous asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 842cf7eba09SNan Zhou } 843cf7eba09SNan Zhou 844cf7eba09SNan Zhou /** 845cf7eba09SNan Zhou * ChassisResetActionInfo derived class for delivering Chassis 846cf7eba09SNan Zhou * ResetType AllowableValues using ResetInfo schema. 847cf7eba09SNan Zhou */ 848cf7eba09SNan Zhou inline void requestRoutesChassisResetActionInfo(App& app) 849cf7eba09SNan Zhou { 850cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/") 851cf7eba09SNan Zhou .privileges(redfish::privileges::getActionInfo) 852cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 853cf7eba09SNan Zhou std::bind_front(handleChassisResetActionInfoGet, std::ref(app))); 8541cb1a9e6SAppaRao Puli } 8551cb1a9e6SAppaRao Puli 856e37f8451SRapkiewicz, Pawel } // namespace redfish 857