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 18b49ac873SJames Feist #include "health.hpp" 191c8fba97SJames Feist #include "led.hpp" 201abe55efSEd Tanous 217e860f15SJohn Edward Broadbent #include <app.hpp> 22e37f8451SRapkiewicz, Pawel #include <boost/container/flat_map.hpp> 23*168e20c1SEd Tanous #include <dbus_utility.hpp> 24ed398213SEd Tanous #include <registries/privilege_registry.hpp> 2502f6ff19SGunnar Mills #include <utils/collection.hpp> 261214b7e7SGunnar Mills 271abe55efSEd Tanous namespace redfish 281abe55efSEd Tanous { 29e37f8451SRapkiewicz, Pawel 30e37f8451SRapkiewicz, Pawel /** 31beeca0aeSGunnar Mills * @brief Retrieves chassis state properties over dbus 32beeca0aeSGunnar Mills * 33beeca0aeSGunnar Mills * @param[in] aResp - Shared pointer for completing asynchronous calls. 34beeca0aeSGunnar Mills * 35beeca0aeSGunnar Mills * @return None. 36beeca0aeSGunnar Mills */ 378d1b46d7Szhanghch05 inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp) 38beeca0aeSGunnar Mills { 39beeca0aeSGunnar Mills crow::connections::systemBus->async_method_call( 40beeca0aeSGunnar Mills [aResp{std::move(aResp)}]( 41beeca0aeSGunnar Mills const boost::system::error_code ec, 42*168e20c1SEd Tanous const dbus::utility::DbusVariantType& chassisState) { 43beeca0aeSGunnar Mills if (ec) 44beeca0aeSGunnar Mills { 45beeca0aeSGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 46beeca0aeSGunnar Mills messages::internalError(aResp->res); 47beeca0aeSGunnar Mills return; 48beeca0aeSGunnar Mills } 49beeca0aeSGunnar Mills 50beeca0aeSGunnar Mills const std::string* s = std::get_if<std::string>(&chassisState); 51beeca0aeSGunnar Mills BMCWEB_LOG_DEBUG << "Chassis state: " << *s; 52beeca0aeSGunnar Mills if (s != nullptr) 53beeca0aeSGunnar Mills { 54beeca0aeSGunnar Mills // Verify Chassis State 55beeca0aeSGunnar Mills if (*s == "xyz.openbmc_project.State.Chassis.PowerState.On") 56beeca0aeSGunnar Mills { 57beeca0aeSGunnar Mills aResp->res.jsonValue["PowerState"] = "On"; 58beeca0aeSGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Enabled"; 59beeca0aeSGunnar Mills } 60beeca0aeSGunnar Mills else if (*s == 61beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis.PowerState.Off") 62beeca0aeSGunnar Mills { 63beeca0aeSGunnar Mills aResp->res.jsonValue["PowerState"] = "Off"; 64beeca0aeSGunnar Mills aResp->res.jsonValue["Status"]["State"] = "StandbyOffline"; 65beeca0aeSGunnar Mills } 66beeca0aeSGunnar Mills } 67beeca0aeSGunnar Mills }, 68beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis", 69beeca0aeSGunnar Mills "/xyz/openbmc_project/state/chassis0", 70beeca0aeSGunnar Mills "org.freedesktop.DBus.Properties", "Get", 71beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis", "CurrentPowerState"); 72beeca0aeSGunnar Mills } 73beeca0aeSGunnar Mills 74beeca0aeSGunnar Mills /** 75e37f8451SRapkiewicz, Pawel * DBus types primitives for several generic DBus interfaces 76e37f8451SRapkiewicz, Pawel * TODO(Pawel) consider move this to separate file into boost::dbus 77e37f8451SRapkiewicz, Pawel */ 78aa2e59c1SEd Tanous using ManagedObjectsType = std::vector<std::pair< 79aa2e59c1SEd Tanous sdbusplus::message::object_path, 80*168e20c1SEd Tanous std::vector<std::pair< 81*168e20c1SEd Tanous std::string, 82*168e20c1SEd Tanous std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>>>>>; 83e37f8451SRapkiewicz, Pawel 84*168e20c1SEd Tanous using PropertiesType = 85*168e20c1SEd Tanous boost::container::flat_map<std::string, dbus::utility::DbusVariantType>; 86e37f8451SRapkiewicz, Pawel 878d1b46d7Szhanghch05 inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp, 88c181942fSQiang XU const std::string& service, 89c181942fSQiang XU const std::string& objPath) 90c181942fSQiang XU { 91c181942fSQiang XU BMCWEB_LOG_DEBUG << "Get intrusion status by service \n"; 92c181942fSQiang XU 93c181942fSQiang XU crow::connections::systemBus->async_method_call( 94c181942fSQiang XU [aResp{std::move(aResp)}](const boost::system::error_code ec, 95*168e20c1SEd Tanous const dbus::utility::DbusVariantType& value) { 96c181942fSQiang XU if (ec) 97c181942fSQiang XU { 984e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 99c181942fSQiang XU // mandatory property 100c181942fSQiang XU BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n"; 101c181942fSQiang XU return; 102c181942fSQiang XU } 103c181942fSQiang XU 104c181942fSQiang XU const std::string* status = std::get_if<std::string>(&value); 105c181942fSQiang XU 106c181942fSQiang XU if (status == nullptr) 107c181942fSQiang XU { 108c181942fSQiang XU BMCWEB_LOG_ERROR << "intrusion status read error \n"; 109c181942fSQiang XU return; 110c181942fSQiang XU } 111c181942fSQiang XU 112c181942fSQiang XU aResp->res.jsonValue["PhysicalSecurity"] = { 113c181942fSQiang XU {"IntrusionSensorNumber", 1}, {"IntrusionSensor", *status}}; 114c181942fSQiang XU }, 115c181942fSQiang XU service, objPath, "org.freedesktop.DBus.Properties", "Get", 116c181942fSQiang XU "xyz.openbmc_project.Chassis.Intrusion", "Status"); 117c181942fSQiang XU } 118c181942fSQiang XU 119c181942fSQiang XU /** 120c181942fSQiang XU * Retrieves physical security properties over dbus 121c181942fSQiang XU */ 1228d1b46d7Szhanghch05 inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp) 123c181942fSQiang XU { 124c181942fSQiang XU crow::connections::systemBus->async_method_call( 125c181942fSQiang XU [aResp{std::move(aResp)}]( 126c181942fSQiang XU const boost::system::error_code ec, 127c181942fSQiang XU const std::vector<std::pair< 128c181942fSQiang XU std::string, 1291214b7e7SGunnar Mills std::vector<std::pair<std::string, std::vector<std::string>>>>>& 1301214b7e7SGunnar Mills subtree) { 131c181942fSQiang XU if (ec) 132c181942fSQiang XU { 1334e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 134c181942fSQiang XU // mandatory property 13554fbf177SAndrew Geissler BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec 136c181942fSQiang XU << "\n"; 137c181942fSQiang XU return; 138c181942fSQiang XU } 139c181942fSQiang XU // Iterate over all retrieved ObjectPaths. 140c181942fSQiang XU for (const auto& object : subtree) 141c181942fSQiang XU { 142c181942fSQiang XU for (const auto& service : object.second) 143c181942fSQiang XU { 144c181942fSQiang XU getIntrusionByService(aResp, service.first, object.first); 145c181942fSQiang XU return; 146c181942fSQiang XU } 147c181942fSQiang XU } 148c181942fSQiang XU }, 149c181942fSQiang XU "xyz.openbmc_project.ObjectMapper", 150c181942fSQiang XU "/xyz/openbmc_project/object_mapper", 151c181942fSQiang XU "xyz.openbmc_project.ObjectMapper", "GetSubTree", 152271584abSEd Tanous "/xyz/openbmc_project/Intrusion", 1, 153c181942fSQiang XU std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"}); 154c181942fSQiang XU } 155c181942fSQiang XU 156e37f8451SRapkiewicz, Pawel /** 157e37f8451SRapkiewicz, Pawel * ChassisCollection derived class for delivering Chassis Collection Schema 158e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 159e37f8451SRapkiewicz, Pawel */ 1607e860f15SJohn Edward Broadbent inline void requestRoutesChassisCollection(App& app) 1611abe55efSEd Tanous { 1627e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/") 163ed398213SEd Tanous .privileges(redfish::privileges::getChassisCollection) 1647e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 1657e860f15SJohn Edward Broadbent [](const crow::Request&, 1667e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1678d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1688d1b46d7Szhanghch05 "#ChassisCollection.ChassisCollection"; 1698d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 1708d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 171e37f8451SRapkiewicz, Pawel 17202f6ff19SGunnar Mills collection_util::getCollectionMembers( 17302f6ff19SGunnar Mills asyncResp, "/redfish/v1/Chassis", 17402f6ff19SGunnar Mills {"xyz.openbmc_project.Inventory.Item.Board", 17502f6ff19SGunnar Mills "xyz.openbmc_project.Inventory.Item.Chassis"}); 1767e860f15SJohn Edward Broadbent }); 17762d5e2e4SEd Tanous } 178e37f8451SRapkiewicz, Pawel 179308f70c7SWilly Tu inline void 180308f70c7SWilly Tu getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 181308f70c7SWilly Tu const std::string& connectionName, 182308f70c7SWilly Tu const std::string& path) 183308f70c7SWilly Tu { 184308f70c7SWilly Tu crow::connections::systemBus->async_method_call( 185308f70c7SWilly Tu [asyncResp](const boost::system::error_code ec, 186*168e20c1SEd Tanous const dbus::utility::DbusVariantType& property) { 187308f70c7SWilly Tu if (ec) 188308f70c7SWilly Tu { 1890fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "DBUS response error for Location"; 190308f70c7SWilly Tu messages::internalError(asyncResp->res); 191308f70c7SWilly Tu return; 192308f70c7SWilly Tu } 193308f70c7SWilly Tu 194308f70c7SWilly Tu const std::string* value = std::get_if<std::string>(&property); 195308f70c7SWilly Tu if (value == nullptr) 196308f70c7SWilly Tu { 1970fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "Null value returned for locaton code"; 198308f70c7SWilly Tu messages::internalError(asyncResp->res); 199308f70c7SWilly Tu return; 200308f70c7SWilly Tu } 201308f70c7SWilly Tu asyncResp->res 202308f70c7SWilly Tu .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = *value; 203308f70c7SWilly Tu }, 204308f70c7SWilly Tu connectionName, path, "org.freedesktop.DBus.Properties", "Get", 205308f70c7SWilly Tu "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode"); 206308f70c7SWilly Tu } 207308f70c7SWilly Tu 208308f70c7SWilly Tu inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 209308f70c7SWilly Tu const std::string& connectionName, 210308f70c7SWilly Tu const std::string& path) 211308f70c7SWilly Tu { 212308f70c7SWilly Tu crow::connections::systemBus->async_method_call( 213308f70c7SWilly Tu [asyncResp](const boost::system::error_code ec, 214*168e20c1SEd Tanous const dbus::utility::DbusVariantType& chassisUUID) { 215308f70c7SWilly Tu if (ec) 216308f70c7SWilly Tu { 2170fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "DBUS response error for UUID"; 218308f70c7SWilly Tu messages::internalError(asyncResp->res); 219308f70c7SWilly Tu return; 220308f70c7SWilly Tu } 221308f70c7SWilly Tu const std::string* value = std::get_if<std::string>(&chassisUUID); 222308f70c7SWilly Tu if (value == nullptr) 223308f70c7SWilly Tu { 2240fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "Null value returned for UUID"; 225308f70c7SWilly Tu messages::internalError(asyncResp->res); 226308f70c7SWilly Tu return; 227308f70c7SWilly Tu } 228308f70c7SWilly Tu asyncResp->res.jsonValue["UUID"] = *value; 229308f70c7SWilly Tu }, 230308f70c7SWilly Tu connectionName, path, "org.freedesktop.DBus.Properties", "Get", 231308f70c7SWilly Tu "xyz.openbmc_project.Common.UUID", "UUID"); 232308f70c7SWilly Tu } 233308f70c7SWilly Tu 234e37f8451SRapkiewicz, Pawel /** 235e37f8451SRapkiewicz, Pawel * Chassis override class for delivering Chassis Schema 236e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 237e37f8451SRapkiewicz, Pawel */ 2387e860f15SJohn Edward Broadbent inline void requestRoutesChassis(App& app) 2391abe55efSEd Tanous { 2407e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 241ed398213SEd Tanous .privileges(redfish::privileges::getChassis) 2427e860f15SJohn Edward Broadbent .methods( 2437e860f15SJohn Edward Broadbent boost::beast::http::verb::get)([](const crow::Request&, 2447e860f15SJohn Edward Broadbent const std::shared_ptr< 2457e860f15SJohn Edward Broadbent bmcweb::AsyncResp>& asyncResp, 2467e860f15SJohn Edward Broadbent const std::string& chassisId) { 247adc4f0dbSShawn McCarney const std::array<const char*, 2> interfaces = { 248734bfe90SGunnar Mills "xyz.openbmc_project.Inventory.Item.Board", 249adc4f0dbSShawn McCarney "xyz.openbmc_project.Inventory.Item.Chassis"}; 250734bfe90SGunnar Mills 25155c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 25262d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 25362d5e2e4SEd Tanous const boost::system::error_code ec, 2541c8fba97SJames Feist const crow::openbmc_mapper::GetSubTreeType& subtree) { 25562d5e2e4SEd Tanous if (ec) 2561abe55efSEd Tanous { 257f12894f8SJason M. Bills messages::internalError(asyncResp->res); 258daf36e2eSEd Tanous return; 259daf36e2eSEd Tanous } 260daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 2611abe55efSEd Tanous for (const std::pair< 2621abe55efSEd Tanous std::string, 2637e860f15SJohn Edward Broadbent std::vector<std::pair<std::string, 2647e860f15SJohn Edward Broadbent std::vector<std::string>>>>& 2651214b7e7SGunnar Mills object : subtree) 2661abe55efSEd Tanous { 267daf36e2eSEd Tanous const std::string& path = object.first; 2681abe55efSEd Tanous const std::vector< 2691214b7e7SGunnar Mills std::pair<std::string, std::vector<std::string>>>& 2701214b7e7SGunnar Mills connectionNames = object.second; 2717e860f15SJohn Edward Broadbent 272997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 273997093ebSGeorge Liu if (objPath.filename() != chassisId) 2741abe55efSEd Tanous { 275daf36e2eSEd Tanous continue; 276daf36e2eSEd Tanous } 27726f03899SShawn McCarney 2787e860f15SJohn Edward Broadbent auto health = 2797e860f15SJohn Edward Broadbent std::make_shared<HealthPopulate>(asyncResp); 280b49ac873SJames Feist 281b49ac873SJames Feist crow::connections::systemBus->async_method_call( 282*168e20c1SEd Tanous [health](const boost::system::error_code ec2, 283*168e20c1SEd Tanous dbus::utility::DbusVariantType& resp) { 28423a21a1cSEd Tanous if (ec2) 285b49ac873SJames Feist { 286b49ac873SJames Feist return; // no sensors = no failures 287b49ac873SJames Feist } 288b49ac873SJames Feist std::vector<std::string>* data = 2897e860f15SJohn Edward Broadbent std::get_if<std::vector<std::string>>( 2907e860f15SJohn Edward Broadbent &resp); 291b49ac873SJames Feist if (data == nullptr) 292b49ac873SJames Feist { 293b49ac873SJames Feist return; 294b49ac873SJames Feist } 295b49ac873SJames Feist health->inventory = std::move(*data); 296b49ac873SJames Feist }, 297b49ac873SJames Feist "xyz.openbmc_project.ObjectMapper", 298b49ac873SJames Feist path + "/all_sensors", 299b49ac873SJames Feist "org.freedesktop.DBus.Properties", "Get", 300b49ac873SJames Feist "xyz.openbmc_project.Association", "endpoints"); 301b49ac873SJames Feist 302b49ac873SJames Feist health->populate(); 303b49ac873SJames Feist 3041abe55efSEd Tanous if (connectionNames.size() < 1) 3051abe55efSEd Tanous { 3061c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 307e0d918bcSEd Tanous continue; 308daf36e2eSEd Tanous } 309e0d918bcSEd Tanous 31049c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.type"] = 3119f8bfa7cSGunnar Mills "#Chassis.v1_14_0.Chassis"; 31249c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.id"] = 31349c53ac9SJohnathan Mantey "/redfish/v1/Chassis/" + chassisId; 31449c53ac9SJohnathan Mantey asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 31549c53ac9SJohnathan Mantey asyncResp->res.jsonValue["ChassisType"] = "RackMount"; 3167e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] = 3177e860f15SJohn Edward Broadbent {{"target", "/redfish/v1/Chassis/" + chassisId + 318dd99e04bSP.K. Lee "/Actions/Chassis.Reset"}, 3191cb1a9e6SAppaRao Puli {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" + 3201cb1a9e6SAppaRao Puli chassisId + 3211cb1a9e6SAppaRao Puli "/ResetActionInfo"}}; 322adbe192aSJason M. Bills asyncResp->res.jsonValue["PCIeDevices"] = { 323adbe192aSJason M. Bills {"@odata.id", 324adbe192aSJason M. Bills "/redfish/v1/Systems/system/PCIeDevices"}}; 32549c53ac9SJohnathan Mantey 32649c53ac9SJohnathan Mantey const std::string& connectionName = 32749c53ac9SJohnathan Mantey connectionNames[0].first; 3281c8fba97SJames Feist 32923a21a1cSEd Tanous const std::vector<std::string>& interfaces2 = 3301c8fba97SJames Feist connectionNames[0].second; 3311c8fba97SJames Feist const std::array<const char*, 2> hasIndicatorLed = { 3321c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 3330fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 3341c8fba97SJames Feist 335476b9cc5STejas Patil const std::string assetTagInterface = 3360fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.AssetTag"; 337476b9cc5STejas Patil if (std::find(interfaces2.begin(), interfaces2.end(), 338476b9cc5STejas Patil assetTagInterface) != interfaces2.end()) 339476b9cc5STejas Patil { 340476b9cc5STejas Patil crow::connections::systemBus->async_method_call( 341476b9cc5STejas Patil [asyncResp, chassisId(std::string(chassisId))]( 342476b9cc5STejas Patil const boost::system::error_code ec, 343*168e20c1SEd Tanous const dbus::utility::DbusVariantType& 344*168e20c1SEd Tanous property) { 345476b9cc5STejas Patil if (ec) 346476b9cc5STejas Patil { 347476b9cc5STejas Patil BMCWEB_LOG_DEBUG 3480fda0f12SGeorge Liu << "DBus response error for AssetTag"; 349476b9cc5STejas Patil messages::internalError(asyncResp->res); 350476b9cc5STejas Patil return; 351476b9cc5STejas Patil } 352476b9cc5STejas Patil 353476b9cc5STejas Patil const std::string* assetTag = 354476b9cc5STejas Patil std::get_if<std::string>(&property); 355476b9cc5STejas Patil if (assetTag == nullptr) 356476b9cc5STejas Patil { 357476b9cc5STejas Patil BMCWEB_LOG_DEBUG 3580fda0f12SGeorge Liu << "Null value returned for Chassis AssetTag"; 359476b9cc5STejas Patil messages::internalError(asyncResp->res); 360476b9cc5STejas Patil return; 361476b9cc5STejas Patil } 362476b9cc5STejas Patil asyncResp->res.jsonValue["AssetTag"] = 363476b9cc5STejas Patil *assetTag; 364476b9cc5STejas Patil }, 365476b9cc5STejas Patil connectionName, path, 366476b9cc5STejas Patil "org.freedesktop.DBus.Properties", "Get", 367476b9cc5STejas Patil assetTagInterface, "AssetTag"); 368476b9cc5STejas Patil } 369476b9cc5STejas Patil 3701c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 3711c8fba97SJames Feist { 3727e860f15SJohn Edward Broadbent if (std::find(interfaces2.begin(), 3737e860f15SJohn Edward Broadbent interfaces2.end(), 37423a21a1cSEd Tanous interface) != interfaces2.end()) 3751c8fba97SJames Feist { 3761c8fba97SJames Feist getIndicatorLedState(asyncResp); 3779f8bfa7cSGunnar Mills getLocationIndicatorActive(asyncResp); 3781c8fba97SJames Feist break; 3791c8fba97SJames Feist } 3801c8fba97SJames Feist } 3811c8fba97SJames Feist 38255c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 38362d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 38490728b54SEd Tanous const boost::system::error_code /*ec2*/, 3857e860f15SJohn Edward Broadbent const std::vector< 386*168e20c1SEd Tanous std::pair<std::string, 387*168e20c1SEd Tanous dbus::utility::DbusVariantType>>& 3887e860f15SJohn Edward Broadbent propertiesList) { 389*168e20c1SEd Tanous for (const std::pair< 390*168e20c1SEd Tanous std::string, 391*168e20c1SEd Tanous dbus::utility::DbusVariantType>& 3921214b7e7SGunnar Mills property : propertiesList) 3931abe55efSEd Tanous { 3947e860f15SJohn Edward Broadbent // Store DBus properties that are also 3957e860f15SJohn Edward Broadbent // Redfish properties with same name and a 3967e860f15SJohn Edward Broadbent // string value 39799cffd7fSShawn McCarney const std::string& propertyName = 39899cffd7fSShawn McCarney property.first; 39999cffd7fSShawn McCarney if ((propertyName == "PartNumber") || 40099cffd7fSShawn McCarney (propertyName == "SerialNumber") || 40199cffd7fSShawn McCarney (propertyName == "Manufacturer") || 402caa11f7aSAlpana Kumari (propertyName == "Model") || 403caa11f7aSAlpana Kumari (propertyName == "SparePartNumber")) 40499cffd7fSShawn McCarney { 405daf36e2eSEd Tanous const std::string* value = 40699cffd7fSShawn McCarney std::get_if<std::string>( 40799cffd7fSShawn McCarney &property.second); 408caa11f7aSAlpana Kumari if (value == nullptr) 4091abe55efSEd Tanous { 410caa11f7aSAlpana Kumari BMCWEB_LOG_ERROR 411caa11f7aSAlpana Kumari << "Null value returned for " 412caa11f7aSAlpana Kumari << propertyName; 413caa11f7aSAlpana Kumari messages::internalError( 414caa11f7aSAlpana Kumari asyncResp->res); 415caa11f7aSAlpana Kumari return; 416daf36e2eSEd Tanous } 417caa11f7aSAlpana Kumari // SparePartNumber is optional on D-Bus 418caa11f7aSAlpana Kumari // so skip if it is empty 419caa11f7aSAlpana Kumari if (propertyName == "SparePartNumber") 420caa11f7aSAlpana Kumari { 421caa11f7aSAlpana Kumari if (*value == "") 422caa11f7aSAlpana Kumari { 423caa11f7aSAlpana Kumari continue; 424caa11f7aSAlpana Kumari } 425caa11f7aSAlpana Kumari } 426caa11f7aSAlpana Kumari asyncResp->res.jsonValue[propertyName] = 427caa11f7aSAlpana Kumari *value; 428daf36e2eSEd Tanous } 42999cffd7fSShawn McCarney } 43062d5e2e4SEd Tanous asyncResp->res.jsonValue["Name"] = chassisId; 43162d5e2e4SEd Tanous asyncResp->res.jsonValue["Id"] = chassisId; 4320256b694Szhanghch05 #ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL 43362d5e2e4SEd Tanous asyncResp->res.jsonValue["Thermal"] = { 4341abe55efSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 4351abe55efSEd Tanous chassisId + "/Thermal"}}; 4362474adfaSEd Tanous // Power object 4372474adfaSEd Tanous asyncResp->res.jsonValue["Power"] = { 4382474adfaSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 4392474adfaSEd Tanous chassisId + "/Power"}}; 4400256b694Szhanghch05 #endif 44195a3ecadSAnthony Wilson // SensorCollection 44295a3ecadSAnthony Wilson asyncResp->res.jsonValue["Sensors"] = { 44395a3ecadSAnthony Wilson {"@odata.id", "/redfish/v1/Chassis/" + 44495a3ecadSAnthony Wilson chassisId + "/Sensors"}}; 445029573d4SEd Tanous asyncResp->res.jsonValue["Status"] = { 446029573d4SEd Tanous {"State", "Enabled"}, 447029573d4SEd Tanous }; 4482474adfaSEd Tanous 449029573d4SEd Tanous asyncResp->res 450029573d4SEd Tanous .jsonValue["Links"]["ComputerSystems"] = { 4517e860f15SJohn Edward Broadbent {{"@odata.id", 4527e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system"}}}; 4537e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Links"]["ManagedBy"] = 4547e860f15SJohn Edward Broadbent {{{"@odata.id", 4557e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc"}}}; 456beeca0aeSGunnar Mills getChassisState(asyncResp); 457daf36e2eSEd Tanous }, 4587e860f15SJohn Edward Broadbent connectionName, path, 4597e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "GetAll", 4601abe55efSEd Tanous "xyz.openbmc_project.Inventory.Decorator.Asset"); 4612c37b4b0SSharad Yadav 462308f70c7SWilly Tu for (const auto& interface : interfaces2) 4632c37b4b0SSharad Yadav { 464308f70c7SWilly Tu if (interface == "xyz.openbmc_project.Common.UUID") 4652c37b4b0SSharad Yadav { 466308f70c7SWilly Tu getChassisUUID(asyncResp, connectionName, path); 4672c37b4b0SSharad Yadav } 4680fda0f12SGeorge Liu else if ( 4690fda0f12SGeorge Liu interface == 4700fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 4712c37b4b0SSharad Yadav { 472308f70c7SWilly Tu getChassisLocationCode(asyncResp, 473308f70c7SWilly Tu connectionName, path); 4742c37b4b0SSharad Yadav } 4752c37b4b0SSharad Yadav } 4762c37b4b0SSharad Yadav 477daf36e2eSEd Tanous return; 478daf36e2eSEd Tanous } 479e0d918bcSEd Tanous 480daf36e2eSEd Tanous // Couldn't find an object with that name. return an error 481f12894f8SJason M. Bills messages::resourceNotFound( 4829f8bfa7cSGunnar Mills asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId); 483daf36e2eSEd Tanous }, 484daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", 485daf36e2eSEd Tanous "/xyz/openbmc_project/object_mapper", 486daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTree", 487271584abSEd Tanous "/xyz/openbmc_project/inventory", 0, interfaces); 488c181942fSQiang XU 489c181942fSQiang XU getPhysicalSecurityData(asyncResp); 4907e860f15SJohn Edward Broadbent }); 4911c8fba97SJames Feist 4927e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 493ed398213SEd Tanous .privileges(redfish::privileges::patchChassis) 4947e860f15SJohn Edward Broadbent .methods( 4957e860f15SJohn Edward Broadbent boost::beast::http::verb:: 4967e860f15SJohn Edward Broadbent patch)([](const crow::Request& req, 4977e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4987e860f15SJohn Edward Broadbent const std::string& param) { 4999f8bfa7cSGunnar Mills std::optional<bool> locationIndicatorActive; 5001c8fba97SJames Feist std::optional<std::string> indicatorLed; 5011c8fba97SJames Feist 5027e860f15SJohn Edward Broadbent if (param.empty()) 5031c8fba97SJames Feist { 5041c8fba97SJames Feist return; 5051c8fba97SJames Feist } 5061c8fba97SJames Feist 5077e860f15SJohn Edward Broadbent if (!json_util::readJson( 5087e860f15SJohn Edward Broadbent req, asyncResp->res, "LocationIndicatorActive", 5097e860f15SJohn Edward Broadbent locationIndicatorActive, "IndicatorLED", indicatorLed)) 5101c8fba97SJames Feist { 5111c8fba97SJames Feist return; 5121c8fba97SJames Feist } 5131c8fba97SJames Feist 5149f8bfa7cSGunnar Mills // TODO (Gunnar): Remove IndicatorLED after enough time has passed 5159f8bfa7cSGunnar Mills if (!locationIndicatorActive && !indicatorLed) 5161c8fba97SJames Feist { 5171c8fba97SJames Feist return; // delete this when we support more patch properties 5181c8fba97SJames Feist } 519d6aa0093SGunnar Mills if (indicatorLed) 520d6aa0093SGunnar Mills { 5217e860f15SJohn Edward Broadbent asyncResp->res.addHeader( 5227e860f15SJohn Edward Broadbent boost::beast::http::field::warning, 5230fda0f12SGeorge Liu "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\""); 524d6aa0093SGunnar Mills } 5251c8fba97SJames Feist 5261c8fba97SJames Feist const std::array<const char*, 2> interfaces = { 5271c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board", 5281c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Chassis"}; 5291c8fba97SJames Feist 5307e860f15SJohn Edward Broadbent const std::string& chassisId = param; 5311c8fba97SJames Feist 5321c8fba97SJames Feist crow::connections::systemBus->async_method_call( 5339f8bfa7cSGunnar Mills [asyncResp, chassisId, locationIndicatorActive, indicatorLed]( 5341c8fba97SJames Feist const boost::system::error_code ec, 5351c8fba97SJames Feist const crow::openbmc_mapper::GetSubTreeType& subtree) { 5361c8fba97SJames Feist if (ec) 5371c8fba97SJames Feist { 5381c8fba97SJames Feist messages::internalError(asyncResp->res); 5391c8fba97SJames Feist return; 5401c8fba97SJames Feist } 5411c8fba97SJames Feist 5421c8fba97SJames Feist // Iterate over all retrieved ObjectPaths. 5431c8fba97SJames Feist for (const std::pair< 5441c8fba97SJames Feist std::string, 5457e860f15SJohn Edward Broadbent std::vector<std::pair<std::string, 5467e860f15SJohn Edward Broadbent std::vector<std::string>>>>& 5471214b7e7SGunnar Mills object : subtree) 5481c8fba97SJames Feist { 5491c8fba97SJames Feist const std::string& path = object.first; 5501c8fba97SJames Feist const std::vector< 5511214b7e7SGunnar Mills std::pair<std::string, std::vector<std::string>>>& 5521214b7e7SGunnar Mills connectionNames = object.second; 5531c8fba97SJames Feist 554997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 555997093ebSGeorge Liu if (objPath.filename() != chassisId) 5561c8fba97SJames Feist { 5571c8fba97SJames Feist continue; 5581c8fba97SJames Feist } 5591c8fba97SJames Feist 5601c8fba97SJames Feist if (connectionNames.size() < 1) 5611c8fba97SJames Feist { 5621c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 5631c8fba97SJames Feist continue; 5641c8fba97SJames Feist } 5651c8fba97SJames Feist 56623a21a1cSEd Tanous const std::vector<std::string>& interfaces3 = 5671c8fba97SJames Feist connectionNames[0].second; 5681c8fba97SJames Feist 5691c8fba97SJames Feist const std::array<const char*, 2> hasIndicatorLed = { 5701c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 5710fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 5721c8fba97SJames Feist bool indicatorChassis = false; 5731c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 5741c8fba97SJames Feist { 5757e860f15SJohn Edward Broadbent if (std::find(interfaces3.begin(), 5767e860f15SJohn Edward Broadbent interfaces3.end(), 57723a21a1cSEd Tanous interface) != interfaces3.end()) 5781c8fba97SJames Feist { 5791c8fba97SJames Feist indicatorChassis = true; 5801c8fba97SJames Feist break; 5811c8fba97SJames Feist } 5821c8fba97SJames Feist } 5839f8bfa7cSGunnar Mills if (locationIndicatorActive) 5849f8bfa7cSGunnar Mills { 5859f8bfa7cSGunnar Mills if (indicatorChassis) 5869f8bfa7cSGunnar Mills { 5879f8bfa7cSGunnar Mills setLocationIndicatorActive( 5889f8bfa7cSGunnar Mills asyncResp, *locationIndicatorActive); 5899f8bfa7cSGunnar Mills } 5909f8bfa7cSGunnar Mills else 5919f8bfa7cSGunnar Mills { 5929f8bfa7cSGunnar Mills messages::propertyUnknown( 5939f8bfa7cSGunnar Mills asyncResp->res, "LocationIndicatorActive"); 5949f8bfa7cSGunnar Mills } 5959f8bfa7cSGunnar Mills } 5969f8bfa7cSGunnar Mills if (indicatorLed) 5979f8bfa7cSGunnar Mills { 5981c8fba97SJames Feist if (indicatorChassis) 5991c8fba97SJames Feist { 600f23b7296SEd Tanous setIndicatorLedState(asyncResp, *indicatorLed); 6011c8fba97SJames Feist } 6021c8fba97SJames Feist else 6031c8fba97SJames Feist { 6041c8fba97SJames Feist messages::propertyUnknown(asyncResp->res, 6051c8fba97SJames Feist "IndicatorLED"); 6061c8fba97SJames Feist } 6071c8fba97SJames Feist } 6081c8fba97SJames Feist return; 6091c8fba97SJames Feist } 6101c8fba97SJames Feist 6111c8fba97SJames Feist messages::resourceNotFound( 6129f8bfa7cSGunnar Mills asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId); 6131c8fba97SJames Feist }, 6141c8fba97SJames Feist "xyz.openbmc_project.ObjectMapper", 6151c8fba97SJames Feist "/xyz/openbmc_project/object_mapper", 6161c8fba97SJames Feist "xyz.openbmc_project.ObjectMapper", "GetSubTree", 6171c8fba97SJames Feist "/xyz/openbmc_project/inventory", 0, interfaces); 6187e860f15SJohn Edward Broadbent }); 6191c8fba97SJames Feist } 620dd99e04bSP.K. Lee 6218d1b46d7Szhanghch05 inline void 6228d1b46d7Szhanghch05 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 623dd99e04bSP.K. Lee { 624c3b3c92aSVijay Khemka const char* busName = "xyz.openbmc_project.ObjectMapper"; 625c3b3c92aSVijay Khemka const char* path = "/xyz/openbmc_project/object_mapper"; 626c3b3c92aSVijay Khemka const char* interface = "xyz.openbmc_project.ObjectMapper"; 627c3b3c92aSVijay Khemka const char* method = "GetSubTreePaths"; 628c3b3c92aSVijay Khemka 629c3b3c92aSVijay Khemka const std::array<const char*, 1> interfaces = { 630c3b3c92aSVijay Khemka "xyz.openbmc_project.State.Chassis"}; 631c3b3c92aSVijay Khemka 632c3b3c92aSVijay Khemka // Use mapper to get subtree paths. 633c3b3c92aSVijay Khemka crow::connections::systemBus->async_method_call( 634c3b3c92aSVijay Khemka [asyncResp](const boost::system::error_code ec, 635c3b3c92aSVijay Khemka const std::vector<std::string>& chassisList) { 636c3b3c92aSVijay Khemka if (ec) 637c3b3c92aSVijay Khemka { 638c3b3c92aSVijay Khemka BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec; 639c3b3c92aSVijay Khemka messages::internalError(asyncResp->res); 640c3b3c92aSVijay Khemka return; 641c3b3c92aSVijay Khemka } 642c3b3c92aSVijay Khemka 643dd99e04bSP.K. Lee const char* processName = "xyz.openbmc_project.State.Chassis"; 644dd99e04bSP.K. Lee const char* interfaceName = "xyz.openbmc_project.State.Chassis"; 645dd99e04bSP.K. Lee const char* destProperty = "RequestedPowerTransition"; 646dd99e04bSP.K. Lee const std::string propertyValue = 647dd99e04bSP.K. Lee "xyz.openbmc_project.State.Chassis.Transition.PowerCycle"; 648c3b3c92aSVijay Khemka std::string objectPath = 649c3b3c92aSVijay Khemka "/xyz/openbmc_project/state/chassis_system0"; 650c3b3c92aSVijay Khemka 651c3b3c92aSVijay Khemka /* Look for system reset chassis path */ 652c3b3c92aSVijay Khemka if ((std::find(chassisList.begin(), chassisList.end(), 653c3b3c92aSVijay Khemka objectPath)) == chassisList.end()) 654c3b3c92aSVijay Khemka { 655c3b3c92aSVijay Khemka /* We prefer to reset the full chassis_system, but if it doesn't 656c3b3c92aSVijay Khemka * exist on some platforms, fall back to a host-only power reset 657c3b3c92aSVijay Khemka */ 658c3b3c92aSVijay Khemka objectPath = "/xyz/openbmc_project/state/chassis0"; 659c3b3c92aSVijay Khemka } 660dd99e04bSP.K. Lee 661dd99e04bSP.K. Lee crow::connections::systemBus->async_method_call( 662dd99e04bSP.K. Lee [asyncResp](const boost::system::error_code ec) { 663dd99e04bSP.K. Lee // Use "Set" method to set the property value. 664dd99e04bSP.K. Lee if (ec) 665dd99e04bSP.K. Lee { 666c3b3c92aSVijay Khemka BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: " 667c3b3c92aSVijay Khemka << ec; 668dd99e04bSP.K. Lee messages::internalError(asyncResp->res); 669dd99e04bSP.K. Lee return; 670dd99e04bSP.K. Lee } 671dd99e04bSP.K. Lee 672dd99e04bSP.K. Lee messages::success(asyncResp->res); 673dd99e04bSP.K. Lee }, 674c3b3c92aSVijay Khemka processName, objectPath, "org.freedesktop.DBus.Properties", 675c3b3c92aSVijay Khemka "Set", interfaceName, destProperty, 676*168e20c1SEd Tanous dbus::utility::DbusVariantType{propertyValue}); 677c3b3c92aSVijay Khemka }, 678c3b3c92aSVijay Khemka busName, path, interface, method, "/", 0, interfaces); 679dd99e04bSP.K. Lee } 680dd99e04bSP.K. Lee 681dd99e04bSP.K. Lee /** 682dd99e04bSP.K. Lee * ChassisResetAction class supports the POST method for the Reset 683dd99e04bSP.K. Lee * action. 684dd99e04bSP.K. Lee * Function handles POST method request. 685dd99e04bSP.K. Lee * Analyzes POST body before sending Reset request data to D-Bus. 686dd99e04bSP.K. Lee */ 6877e860f15SJohn Edward Broadbent 6887e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetAction(App& app) 689dd99e04bSP.K. Lee { 6907e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/") 691ed398213SEd Tanous .privileges(redfish::privileges::postChassis) 6927e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 6937e860f15SJohn Edward Broadbent [](const crow::Request& req, 6947e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6957e860f15SJohn Edward Broadbent const std::string&) { 696dd99e04bSP.K. Lee BMCWEB_LOG_DEBUG << "Post Chassis Reset."; 697dd99e04bSP.K. Lee 698dd99e04bSP.K. Lee std::string resetType; 699dd99e04bSP.K. Lee 7007e860f15SJohn Edward Broadbent if (!json_util::readJson(req, asyncResp->res, "ResetType", 7017e860f15SJohn Edward Broadbent resetType)) 702dd99e04bSP.K. Lee { 703dd99e04bSP.K. Lee return; 704dd99e04bSP.K. Lee } 705dd99e04bSP.K. Lee 706dd99e04bSP.K. Lee if (resetType != "PowerCycle") 707dd99e04bSP.K. Lee { 708dd99e04bSP.K. Lee BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: " 709dd99e04bSP.K. Lee << resetType; 7107e860f15SJohn Edward Broadbent messages::actionParameterNotSupported( 7117e860f15SJohn Edward Broadbent asyncResp->res, resetType, "ResetType"); 712dd99e04bSP.K. Lee 713dd99e04bSP.K. Lee return; 714dd99e04bSP.K. Lee } 715dd99e04bSP.K. Lee doChassisPowerCycle(asyncResp); 7167e860f15SJohn Edward Broadbent }); 717dd99e04bSP.K. Lee } 7181cb1a9e6SAppaRao Puli 7191cb1a9e6SAppaRao Puli /** 7201cb1a9e6SAppaRao Puli * ChassisResetActionInfo derived class for delivering Chassis 7211cb1a9e6SAppaRao Puli * ResetType AllowableValues using ResetInfo schema. 7221cb1a9e6SAppaRao Puli */ 7237e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetActionInfo(App& app) 7241cb1a9e6SAppaRao Puli { 7257e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/") 726ed398213SEd Tanous .privileges(redfish::privileges::getActionInfo) 7277e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 7287e860f15SJohn Edward Broadbent [](const crow::Request&, 7297e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 7307e860f15SJohn Edward Broadbent const std::string& chassisId) 7311cb1a9e6SAppaRao Puli 7321cb1a9e6SAppaRao Puli { 7338d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 7348d1b46d7Szhanghch05 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"}, 7358d1b46d7Szhanghch05 {"@odata.id", 7368d1b46d7Szhanghch05 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"}, 7371cb1a9e6SAppaRao Puli {"Name", "Reset Action Info"}, 7381cb1a9e6SAppaRao Puli {"Id", "ResetActionInfo"}, 7391cb1a9e6SAppaRao Puli {"Parameters", 7401cb1a9e6SAppaRao Puli {{{"Name", "ResetType"}, 7411cb1a9e6SAppaRao Puli {"Required", true}, 7421cb1a9e6SAppaRao Puli {"DataType", "String"}, 7431cb1a9e6SAppaRao Puli {"AllowableValues", {"PowerCycle"}}}}}}; 7447e860f15SJohn Edward Broadbent }); 7451cb1a9e6SAppaRao Puli } 7461cb1a9e6SAppaRao Puli 747e37f8451SRapkiewicz, Pawel } // namespace redfish 748