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> 22168e20c1SEd Tanous #include <dbus_utility.hpp> 2345ca1b86SEd Tanous #include <query.hpp> 24ed398213SEd Tanous #include <registries/privilege_registry.hpp> 251e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp> 2602f6ff19SGunnar Mills #include <utils/collection.hpp> 271214b7e7SGunnar Mills 281abe55efSEd Tanous namespace redfish 291abe55efSEd Tanous { 30e37f8451SRapkiewicz, Pawel 31e37f8451SRapkiewicz, Pawel /** 32beeca0aeSGunnar Mills * @brief Retrieves chassis state properties over dbus 33beeca0aeSGunnar Mills * 34beeca0aeSGunnar Mills * @param[in] aResp - Shared pointer for completing asynchronous calls. 35beeca0aeSGunnar Mills * 36beeca0aeSGunnar Mills * @return None. 37beeca0aeSGunnar Mills */ 388d1b46d7Szhanghch05 inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp) 39beeca0aeSGunnar Mills { 401e1e598dSJonathan Doman // crow::connections::systemBus->async_method_call( 411e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 421e1e598dSJonathan Doman *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis", 431e1e598dSJonathan Doman "/xyz/openbmc_project/state/chassis0", 441e1e598dSJonathan Doman "xyz.openbmc_project.State.Chassis", "CurrentPowerState", 451e1e598dSJonathan Doman [aResp{std::move(aResp)}](const boost::system::error_code ec, 461e1e598dSJonathan Doman const std::string& chassisState) { 47beeca0aeSGunnar Mills if (ec) 48beeca0aeSGunnar Mills { 49a6e5e0abSCarson Labrado if (ec == boost::system::errc::host_unreachable) 50a6e5e0abSCarson Labrado { 51a6e5e0abSCarson Labrado // Service not available, no error, just don't return 52a6e5e0abSCarson Labrado // chassis state info 53a6e5e0abSCarson Labrado BMCWEB_LOG_DEBUG << "Service not available " << ec; 54a6e5e0abSCarson Labrado return; 55a6e5e0abSCarson Labrado } 56beeca0aeSGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 57beeca0aeSGunnar Mills messages::internalError(aResp->res); 58beeca0aeSGunnar Mills return; 59beeca0aeSGunnar Mills } 60beeca0aeSGunnar Mills 611e1e598dSJonathan Doman BMCWEB_LOG_DEBUG << "Chassis state: " << chassisState; 62beeca0aeSGunnar Mills // Verify Chassis State 63002d39b4SEd Tanous if (chassisState == "xyz.openbmc_project.State.Chassis.PowerState.On") 64beeca0aeSGunnar Mills { 65beeca0aeSGunnar Mills aResp->res.jsonValue["PowerState"] = "On"; 66beeca0aeSGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Enabled"; 67beeca0aeSGunnar Mills } 681e1e598dSJonathan Doman else if (chassisState == 69beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis.PowerState.Off") 70beeca0aeSGunnar Mills { 71beeca0aeSGunnar Mills aResp->res.jsonValue["PowerState"] = "Off"; 72beeca0aeSGunnar Mills aResp->res.jsonValue["Status"]["State"] = "StandbyOffline"; 73beeca0aeSGunnar Mills } 741e1e598dSJonathan Doman }); 75beeca0aeSGunnar Mills } 76beeca0aeSGunnar Mills 778d1b46d7Szhanghch05 inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp, 78c181942fSQiang XU const std::string& service, 79c181942fSQiang XU const std::string& objPath) 80c181942fSQiang XU { 81c181942fSQiang XU BMCWEB_LOG_DEBUG << "Get intrusion status by service \n"; 82c181942fSQiang XU 831e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 841e1e598dSJonathan Doman *crow::connections::systemBus, service, objPath, 851e1e598dSJonathan Doman "xyz.openbmc_project.Chassis.Intrusion", "Status", 86c181942fSQiang XU [aResp{std::move(aResp)}](const boost::system::error_code ec, 871e1e598dSJonathan Doman const std::string& value) { 88c181942fSQiang XU if (ec) 89c181942fSQiang XU { 904e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 91c181942fSQiang XU // mandatory property 92c181942fSQiang XU BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n"; 93c181942fSQiang XU return; 94c181942fSQiang XU } 95c181942fSQiang XU 96002d39b4SEd Tanous aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensorNumber"] = 1; 971476687dSEd Tanous aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensor"] = value; 981e1e598dSJonathan Doman }); 99c181942fSQiang XU } 100c181942fSQiang XU 101c181942fSQiang XU /** 102c181942fSQiang XU * Retrieves physical security properties over dbus 103c181942fSQiang XU */ 1048d1b46d7Szhanghch05 inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp) 105c181942fSQiang XU { 106c181942fSQiang XU crow::connections::systemBus->async_method_call( 107c181942fSQiang XU [aResp{std::move(aResp)}]( 108c181942fSQiang XU const boost::system::error_code ec, 109b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 110c181942fSQiang XU if (ec) 111c181942fSQiang XU { 1124e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 113c181942fSQiang XU // mandatory property 114002d39b4SEd Tanous BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec << "\n"; 115c181942fSQiang XU return; 116c181942fSQiang XU } 117c181942fSQiang XU // Iterate over all retrieved ObjectPaths. 118c181942fSQiang XU for (const auto& object : subtree) 119c181942fSQiang XU { 120c181942fSQiang XU for (const auto& service : object.second) 121c181942fSQiang XU { 122c181942fSQiang XU getIntrusionByService(aResp, service.first, object.first); 123c181942fSQiang XU return; 124c181942fSQiang XU } 125c181942fSQiang XU } 126c181942fSQiang XU }, 127c181942fSQiang XU "xyz.openbmc_project.ObjectMapper", 128c181942fSQiang XU "/xyz/openbmc_project/object_mapper", 129c181942fSQiang XU "xyz.openbmc_project.ObjectMapper", "GetSubTree", 130271584abSEd Tanous "/xyz/openbmc_project/Intrusion", 1, 131c181942fSQiang XU std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"}); 132c181942fSQiang XU } 133c181942fSQiang XU 134e37f8451SRapkiewicz, Pawel /** 135e37f8451SRapkiewicz, Pawel * ChassisCollection derived class for delivering Chassis Collection Schema 136e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 137e37f8451SRapkiewicz, Pawel */ 1387e860f15SJohn Edward Broadbent inline void requestRoutesChassisCollection(App& app) 1391abe55efSEd Tanous { 1407e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/") 141ed398213SEd Tanous .privileges(redfish::privileges::getChassisCollection) 1427e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 14345ca1b86SEd Tanous [&app](const crow::Request& req, 1447e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 14545ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 14645ca1b86SEd Tanous { 14745ca1b86SEd Tanous return; 14845ca1b86SEd Tanous } 1498d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1508d1b46d7Szhanghch05 "#ChassisCollection.ChassisCollection"; 1518d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 1528d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 153e37f8451SRapkiewicz, Pawel 15402f6ff19SGunnar Mills collection_util::getCollectionMembers( 15502f6ff19SGunnar Mills asyncResp, "/redfish/v1/Chassis", 15602f6ff19SGunnar Mills {"xyz.openbmc_project.Inventory.Item.Board", 15702f6ff19SGunnar Mills "xyz.openbmc_project.Inventory.Item.Chassis"}); 1587e860f15SJohn Edward Broadbent }); 15962d5e2e4SEd Tanous } 160e37f8451SRapkiewicz, Pawel 161308f70c7SWilly Tu inline void 162308f70c7SWilly Tu getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 163308f70c7SWilly Tu const std::string& connectionName, 164308f70c7SWilly Tu const std::string& path) 165308f70c7SWilly Tu { 1661e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 1671e1e598dSJonathan Doman *crow::connections::systemBus, connectionName, path, 1681e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 169308f70c7SWilly Tu [asyncResp](const boost::system::error_code ec, 1701e1e598dSJonathan Doman const std::string& property) { 171308f70c7SWilly Tu if (ec) 172308f70c7SWilly Tu { 1730fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "DBUS response error for Location"; 174308f70c7SWilly Tu messages::internalError(asyncResp->res); 175308f70c7SWilly Tu return; 176308f70c7SWilly Tu } 177308f70c7SWilly Tu 178002d39b4SEd Tanous asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 1791e1e598dSJonathan Doman property; 1801e1e598dSJonathan Doman }); 181308f70c7SWilly Tu } 182308f70c7SWilly Tu 183308f70c7SWilly Tu inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 184308f70c7SWilly Tu const std::string& connectionName, 185308f70c7SWilly Tu const std::string& path) 186308f70c7SWilly Tu { 1871e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 1881e1e598dSJonathan Doman *crow::connections::systemBus, connectionName, path, 1891e1e598dSJonathan Doman "xyz.openbmc_project.Common.UUID", "UUID", 190308f70c7SWilly Tu [asyncResp](const boost::system::error_code ec, 1911e1e598dSJonathan Doman const std::string& chassisUUID) { 192308f70c7SWilly Tu if (ec) 193308f70c7SWilly Tu { 1940fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "DBUS response error for UUID"; 195308f70c7SWilly Tu messages::internalError(asyncResp->res); 196308f70c7SWilly Tu return; 197308f70c7SWilly Tu } 1981e1e598dSJonathan Doman asyncResp->res.jsonValue["UUID"] = chassisUUID; 1991e1e598dSJonathan Doman }); 200308f70c7SWilly Tu } 201308f70c7SWilly Tu 202e37f8451SRapkiewicz, Pawel /** 203e37f8451SRapkiewicz, Pawel * Chassis override class for delivering Chassis Schema 204e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 205e37f8451SRapkiewicz, Pawel */ 2067e860f15SJohn Edward Broadbent inline void requestRoutesChassis(App& app) 2071abe55efSEd Tanous { 2087e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 209ed398213SEd Tanous .privileges(redfish::privileges::getChassis) 210002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 211002d39b4SEd Tanous [&app](const crow::Request& req, 21245ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2137e860f15SJohn Edward Broadbent const std::string& chassisId) { 21445ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 21545ca1b86SEd Tanous { 21645ca1b86SEd Tanous return; 21745ca1b86SEd Tanous } 218adc4f0dbSShawn McCarney const std::array<const char*, 2> interfaces = { 219734bfe90SGunnar Mills "xyz.openbmc_project.Inventory.Item.Board", 220adc4f0dbSShawn McCarney "xyz.openbmc_project.Inventory.Item.Chassis"}; 221734bfe90SGunnar Mills 22255c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 22362d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 22462d5e2e4SEd Tanous const boost::system::error_code ec, 225b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 22662d5e2e4SEd Tanous if (ec) 2271abe55efSEd Tanous { 228f12894f8SJason M. Bills messages::internalError(asyncResp->res); 229daf36e2eSEd Tanous return; 230daf36e2eSEd Tanous } 231daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 232002d39b4SEd Tanous for (const std::pair<std::string, 233002d39b4SEd Tanous std::vector<std::pair< 234002d39b4SEd Tanous std::string, std::vector<std::string>>>>& 2351214b7e7SGunnar Mills object : subtree) 2361abe55efSEd Tanous { 237daf36e2eSEd Tanous const std::string& path = object.first; 2381abe55efSEd Tanous const std::vector< 2391214b7e7SGunnar Mills std::pair<std::string, std::vector<std::string>>>& 2401214b7e7SGunnar Mills connectionNames = object.second; 2417e860f15SJohn Edward Broadbent 242997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 243997093ebSGeorge Liu if (objPath.filename() != chassisId) 2441abe55efSEd Tanous { 245daf36e2eSEd Tanous continue; 246daf36e2eSEd Tanous } 24726f03899SShawn McCarney 248002d39b4SEd Tanous auto health = std::make_shared<HealthPopulate>(asyncResp); 249b49ac873SJames Feist 2501e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::vector<std::string>>( 2511e1e598dSJonathan Doman *crow::connections::systemBus, 252002d39b4SEd Tanous "xyz.openbmc_project.ObjectMapper", path + "/all_sensors", 2531e1e598dSJonathan Doman "xyz.openbmc_project.Association", "endpoints", 254168e20c1SEd Tanous [health](const boost::system::error_code ec2, 2551e1e598dSJonathan Doman const std::vector<std::string>& resp) { 25623a21a1cSEd Tanous if (ec2) 257b49ac873SJames Feist { 258b49ac873SJames Feist return; // no sensors = no failures 259b49ac873SJames Feist } 2601e1e598dSJonathan Doman health->inventory = resp; 2611e1e598dSJonathan Doman }); 262b49ac873SJames Feist 263b49ac873SJames Feist health->populate(); 264b49ac873SJames Feist 26526f6976fSEd Tanous if (connectionNames.empty()) 2661abe55efSEd Tanous { 2671c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 268e0d918bcSEd Tanous continue; 269daf36e2eSEd Tanous } 270e0d918bcSEd Tanous 27149c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.type"] = 2725ac5a2f4SGunnar Mills "#Chassis.v1_16_0.Chassis"; 27349c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.id"] = 27449c53ac9SJohnathan Mantey "/redfish/v1/Chassis/" + chassisId; 27549c53ac9SJohnathan Mantey asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 27649c53ac9SJohnathan Mantey asyncResp->res.jsonValue["ChassisType"] = "RackMount"; 2771476687dSEd Tanous asyncResp->res 2781476687dSEd Tanous .jsonValue["Actions"]["#Chassis.Reset"]["target"] = 2791476687dSEd Tanous "/redfish/v1/Chassis/" + chassisId + 2801476687dSEd Tanous "/Actions/Chassis.Reset"; 2811476687dSEd Tanous asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] 2821476687dSEd Tanous ["@Redfish.ActionInfo"] = 283002d39b4SEd Tanous "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"; 2841476687dSEd Tanous asyncResp->res.jsonValue["PCIeDevices"]["@odata.id"] = 2851476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices"; 28649c53ac9SJohnathan Mantey 28792903bd4SJohn Edward Broadbent sdbusplus::asio::getProperty<std::vector<std::string>>( 28892903bd4SJohn Edward Broadbent *crow::connections::systemBus, 28992903bd4SJohn Edward Broadbent "xyz.openbmc_project.ObjectMapper", path + "/drive", 29092903bd4SJohn Edward Broadbent "xyz.openbmc_project.Association", "endpoints", 29192903bd4SJohn Edward Broadbent [asyncResp, 29292903bd4SJohn Edward Broadbent chassisId](const boost::system::error_code ec3, 29392903bd4SJohn Edward Broadbent const std::vector<std::string>& resp) { 29492903bd4SJohn Edward Broadbent if (ec3 || resp.empty()) 29592903bd4SJohn Edward Broadbent { 29692903bd4SJohn Edward Broadbent return; // no drives = no failures 29792903bd4SJohn Edward Broadbent } 29892903bd4SJohn Edward Broadbent 29992903bd4SJohn Edward Broadbent nlohmann::json reference; 30092903bd4SJohn Edward Broadbent reference["odata.id"] = crow::utility::urlFromPieces( 30192903bd4SJohn Edward Broadbent "redfish", "v1", "Chassis", chassisId, "Drives"); 30292903bd4SJohn Edward Broadbent asyncResp->res.jsonValue["Drives"] = std::move(reference); 30392903bd4SJohn Edward Broadbent }); 30492903bd4SJohn Edward Broadbent 305002d39b4SEd Tanous const std::string& connectionName = connectionNames[0].first; 3061c8fba97SJames Feist 30723a21a1cSEd Tanous const std::vector<std::string>& interfaces2 = 3081c8fba97SJames Feist connectionNames[0].second; 3091c8fba97SJames Feist const std::array<const char*, 2> hasIndicatorLed = { 3101c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 3110fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 3121c8fba97SJames Feist 313476b9cc5STejas Patil const std::string assetTagInterface = 3140fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.AssetTag"; 315476b9cc5STejas Patil if (std::find(interfaces2.begin(), interfaces2.end(), 316476b9cc5STejas Patil assetTagInterface) != interfaces2.end()) 317476b9cc5STejas Patil { 3181e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 319002d39b4SEd Tanous *crow::connections::systemBus, connectionName, path, 320002d39b4SEd Tanous assetTagInterface, "AssetTag", 321476b9cc5STejas Patil [asyncResp, chassisId(std::string(chassisId))]( 322476b9cc5STejas Patil const boost::system::error_code ec, 3231e1e598dSJonathan Doman const std::string& property) { 324476b9cc5STejas Patil if (ec) 325476b9cc5STejas Patil { 326476b9cc5STejas Patil BMCWEB_LOG_DEBUG 3270fda0f12SGeorge Liu << "DBus response error for AssetTag"; 328476b9cc5STejas Patil messages::internalError(asyncResp->res); 329476b9cc5STejas Patil return; 330476b9cc5STejas Patil } 331002d39b4SEd Tanous asyncResp->res.jsonValue["AssetTag"] = property; 3321e1e598dSJonathan Doman }); 333476b9cc5STejas Patil } 334476b9cc5STejas Patil 3351c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 3361c8fba97SJames Feist { 337002d39b4SEd Tanous if (std::find(interfaces2.begin(), interfaces2.end(), 33823a21a1cSEd Tanous interface) != interfaces2.end()) 3391c8fba97SJames Feist { 3401c8fba97SJames Feist getIndicatorLedState(asyncResp); 3419f8bfa7cSGunnar Mills getLocationIndicatorActive(asyncResp); 3421c8fba97SJames Feist break; 3431c8fba97SJames Feist } 3441c8fba97SJames Feist } 3451c8fba97SJames Feist 34655c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 34762d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 34890728b54SEd Tanous const boost::system::error_code /*ec2*/, 349b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& 3507e860f15SJohn Edward Broadbent propertiesList) { 351002d39b4SEd Tanous for (const std::pair<std::string, 352168e20c1SEd Tanous dbus::utility::DbusVariantType>& 3531214b7e7SGunnar Mills property : propertiesList) 3541abe55efSEd Tanous { 3557e860f15SJohn Edward Broadbent // Store DBus properties that are also 3567e860f15SJohn Edward Broadbent // Redfish properties with same name and a 3577e860f15SJohn Edward Broadbent // string value 358002d39b4SEd Tanous const std::string& propertyName = property.first; 35999cffd7fSShawn McCarney if ((propertyName == "PartNumber") || 36099cffd7fSShawn McCarney (propertyName == "SerialNumber") || 36199cffd7fSShawn McCarney (propertyName == "Manufacturer") || 362caa11f7aSAlpana Kumari (propertyName == "Model") || 363caa11f7aSAlpana Kumari (propertyName == "SparePartNumber")) 36499cffd7fSShawn McCarney { 365daf36e2eSEd Tanous const std::string* value = 366002d39b4SEd Tanous std::get_if<std::string>(&property.second); 367caa11f7aSAlpana Kumari if (value == nullptr) 3681abe55efSEd Tanous { 369002d39b4SEd Tanous BMCWEB_LOG_ERROR << "Null value returned for " 370caa11f7aSAlpana Kumari << propertyName; 371002d39b4SEd Tanous messages::internalError(asyncResp->res); 372caa11f7aSAlpana Kumari return; 373daf36e2eSEd Tanous } 374caa11f7aSAlpana Kumari // SparePartNumber is optional on D-Bus 375caa11f7aSAlpana Kumari // so skip if it is empty 376caa11f7aSAlpana Kumari if (propertyName == "SparePartNumber") 377caa11f7aSAlpana Kumari { 37826f6976fSEd Tanous if (value->empty()) 379caa11f7aSAlpana Kumari { 380caa11f7aSAlpana Kumari continue; 381caa11f7aSAlpana Kumari } 382caa11f7aSAlpana Kumari } 383002d39b4SEd Tanous asyncResp->res.jsonValue[propertyName] = *value; 384daf36e2eSEd Tanous } 38599cffd7fSShawn McCarney } 38662d5e2e4SEd Tanous asyncResp->res.jsonValue["Name"] = chassisId; 38762d5e2e4SEd Tanous asyncResp->res.jsonValue["Id"] = chassisId; 3880256b694Szhanghch05 #ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL 389002d39b4SEd Tanous asyncResp->res.jsonValue["Thermal"]["@odata.id"] = 390002d39b4SEd Tanous "/redfish/v1/Chassis/" + chassisId + "/Thermal"; 3912474adfaSEd Tanous // Power object 3921476687dSEd Tanous asyncResp->res.jsonValue["Power"]["@odata.id"] = 393002d39b4SEd Tanous "/redfish/v1/Chassis/" + chassisId + "/Power"; 3940256b694Szhanghch05 #endif 39595a3ecadSAnthony Wilson // SensorCollection 396002d39b4SEd Tanous asyncResp->res.jsonValue["Sensors"]["@odata.id"] = 397002d39b4SEd Tanous "/redfish/v1/Chassis/" + chassisId + "/Sensors"; 398002d39b4SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 3991476687dSEd Tanous 4001476687dSEd Tanous nlohmann::json::array_t computerSystems; 4011476687dSEd Tanous nlohmann::json::object_t system; 402002d39b4SEd Tanous system["@odata.id"] = "/redfish/v1/Systems/system"; 4031476687dSEd Tanous computerSystems.push_back(std::move(system)); 404002d39b4SEd Tanous asyncResp->res.jsonValue["Links"]["ComputerSystems"] = 4051476687dSEd Tanous std::move(computerSystems); 4061476687dSEd Tanous 4071476687dSEd Tanous nlohmann::json::array_t managedBy; 4081476687dSEd Tanous nlohmann::json::object_t manager; 409002d39b4SEd Tanous manager["@odata.id"] = "/redfish/v1/Managers/bmc"; 4101476687dSEd Tanous managedBy.push_back(std::move(manager)); 4117e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Links"]["ManagedBy"] = 4121476687dSEd Tanous std::move(managedBy); 413beeca0aeSGunnar Mills getChassisState(asyncResp); 414daf36e2eSEd Tanous }, 415002d39b4SEd Tanous connectionName, path, "org.freedesktop.DBus.Properties", 416002d39b4SEd Tanous "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset"); 4172c37b4b0SSharad Yadav 418308f70c7SWilly Tu for (const auto& interface : interfaces2) 4192c37b4b0SSharad Yadav { 420308f70c7SWilly Tu if (interface == "xyz.openbmc_project.Common.UUID") 4212c37b4b0SSharad Yadav { 422308f70c7SWilly Tu getChassisUUID(asyncResp, connectionName, path); 4232c37b4b0SSharad Yadav } 4240fda0f12SGeorge Liu else if ( 4250fda0f12SGeorge Liu interface == 4260fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 4272c37b4b0SSharad Yadav { 428002d39b4SEd Tanous getChassisLocationCode(asyncResp, connectionName, path); 4292c37b4b0SSharad Yadav } 4302c37b4b0SSharad Yadav } 4312c37b4b0SSharad Yadav 432daf36e2eSEd Tanous return; 433daf36e2eSEd Tanous } 434e0d918bcSEd Tanous 435daf36e2eSEd Tanous // Couldn't find an object with that name. return an error 436002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, 437002d39b4SEd Tanous "#Chassis.v1_16_0.Chassis", chassisId); 438daf36e2eSEd Tanous }, 439daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", 440daf36e2eSEd Tanous "/xyz/openbmc_project/object_mapper", 441daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTree", 442271584abSEd Tanous "/xyz/openbmc_project/inventory", 0, interfaces); 443c181942fSQiang XU 444c181942fSQiang XU getPhysicalSecurityData(asyncResp); 4457e860f15SJohn Edward Broadbent }); 4461c8fba97SJames Feist 4477e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 448ed398213SEd Tanous .privileges(redfish::privileges::patchChassis) 449002d39b4SEd Tanous .methods(boost::beast::http::verb::patch)( 450002d39b4SEd Tanous [&app](const crow::Request& req, 4517e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4527e860f15SJohn Edward Broadbent const std::string& param) { 45345ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 45445ca1b86SEd Tanous { 45545ca1b86SEd Tanous return; 45645ca1b86SEd Tanous } 4579f8bfa7cSGunnar Mills std::optional<bool> locationIndicatorActive; 4581c8fba97SJames Feist std::optional<std::string> indicatorLed; 4591c8fba97SJames Feist 4607e860f15SJohn Edward Broadbent if (param.empty()) 4611c8fba97SJames Feist { 4621c8fba97SJames Feist return; 4631c8fba97SJames Feist } 4641c8fba97SJames Feist 46515ed6780SWilly Tu if (!json_util::readJsonPatch( 4667e860f15SJohn Edward Broadbent req, asyncResp->res, "LocationIndicatorActive", 4677e860f15SJohn Edward Broadbent locationIndicatorActive, "IndicatorLED", indicatorLed)) 4681c8fba97SJames Feist { 4691c8fba97SJames Feist return; 4701c8fba97SJames Feist } 4711c8fba97SJames Feist 4729f8bfa7cSGunnar Mills // TODO (Gunnar): Remove IndicatorLED after enough time has passed 4739f8bfa7cSGunnar Mills if (!locationIndicatorActive && !indicatorLed) 4741c8fba97SJames Feist { 4751c8fba97SJames Feist return; // delete this when we support more patch properties 4761c8fba97SJames Feist } 477d6aa0093SGunnar Mills if (indicatorLed) 478d6aa0093SGunnar Mills { 4797e860f15SJohn Edward Broadbent asyncResp->res.addHeader( 4807e860f15SJohn Edward Broadbent boost::beast::http::field::warning, 4810fda0f12SGeorge Liu "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\""); 482d6aa0093SGunnar Mills } 4831c8fba97SJames Feist 4841c8fba97SJames Feist const std::array<const char*, 2> interfaces = { 4851c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board", 4861c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Chassis"}; 4871c8fba97SJames Feist 4887e860f15SJohn Edward Broadbent const std::string& chassisId = param; 4891c8fba97SJames Feist 4901c8fba97SJames Feist crow::connections::systemBus->async_method_call( 4919f8bfa7cSGunnar Mills [asyncResp, chassisId, locationIndicatorActive, indicatorLed]( 4921c8fba97SJames Feist const boost::system::error_code ec, 493b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 4941c8fba97SJames Feist if (ec) 4951c8fba97SJames Feist { 4961c8fba97SJames Feist messages::internalError(asyncResp->res); 4971c8fba97SJames Feist return; 4981c8fba97SJames Feist } 4991c8fba97SJames Feist 5001c8fba97SJames Feist // Iterate over all retrieved ObjectPaths. 501002d39b4SEd Tanous for (const std::pair<std::string, 502002d39b4SEd Tanous std::vector<std::pair< 503002d39b4SEd Tanous std::string, std::vector<std::string>>>>& 5041214b7e7SGunnar Mills object : subtree) 5051c8fba97SJames Feist { 5061c8fba97SJames Feist const std::string& path = object.first; 5071c8fba97SJames Feist const std::vector< 5081214b7e7SGunnar Mills std::pair<std::string, std::vector<std::string>>>& 5091214b7e7SGunnar Mills connectionNames = object.second; 5101c8fba97SJames Feist 511997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 512997093ebSGeorge Liu if (objPath.filename() != chassisId) 5131c8fba97SJames Feist { 5141c8fba97SJames Feist continue; 5151c8fba97SJames Feist } 5161c8fba97SJames Feist 51726f6976fSEd Tanous if (connectionNames.empty()) 5181c8fba97SJames Feist { 5191c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 5201c8fba97SJames Feist continue; 5211c8fba97SJames Feist } 5221c8fba97SJames Feist 52323a21a1cSEd Tanous const std::vector<std::string>& interfaces3 = 5241c8fba97SJames Feist connectionNames[0].second; 5251c8fba97SJames Feist 5261c8fba97SJames Feist const std::array<const char*, 2> hasIndicatorLed = { 5271c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 5280fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 5291c8fba97SJames Feist bool indicatorChassis = false; 5301c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 5311c8fba97SJames Feist { 532002d39b4SEd Tanous if (std::find(interfaces3.begin(), interfaces3.end(), 53323a21a1cSEd Tanous interface) != interfaces3.end()) 5341c8fba97SJames Feist { 5351c8fba97SJames Feist indicatorChassis = true; 5361c8fba97SJames Feist break; 5371c8fba97SJames Feist } 5381c8fba97SJames Feist } 5399f8bfa7cSGunnar Mills if (locationIndicatorActive) 5409f8bfa7cSGunnar Mills { 5419f8bfa7cSGunnar Mills if (indicatorChassis) 5429f8bfa7cSGunnar Mills { 543002d39b4SEd Tanous setLocationIndicatorActive(asyncResp, 544002d39b4SEd Tanous *locationIndicatorActive); 5459f8bfa7cSGunnar Mills } 5469f8bfa7cSGunnar Mills else 5479f8bfa7cSGunnar Mills { 548002d39b4SEd Tanous messages::propertyUnknown(asyncResp->res, 549002d39b4SEd Tanous "LocationIndicatorActive"); 5509f8bfa7cSGunnar Mills } 5519f8bfa7cSGunnar Mills } 5529f8bfa7cSGunnar Mills if (indicatorLed) 5539f8bfa7cSGunnar Mills { 5541c8fba97SJames Feist if (indicatorChassis) 5551c8fba97SJames Feist { 556f23b7296SEd Tanous setIndicatorLedState(asyncResp, *indicatorLed); 5571c8fba97SJames Feist } 5581c8fba97SJames Feist else 5591c8fba97SJames Feist { 5601c8fba97SJames Feist messages::propertyUnknown(asyncResp->res, 5611c8fba97SJames Feist "IndicatorLED"); 5621c8fba97SJames Feist } 5631c8fba97SJames Feist } 5641c8fba97SJames Feist return; 5651c8fba97SJames Feist } 5661c8fba97SJames Feist 567002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, 568002d39b4SEd Tanous "#Chassis.v1_14_0.Chassis", chassisId); 5691c8fba97SJames Feist }, 5701c8fba97SJames Feist "xyz.openbmc_project.ObjectMapper", 5711c8fba97SJames Feist "/xyz/openbmc_project/object_mapper", 5721c8fba97SJames Feist "xyz.openbmc_project.ObjectMapper", "GetSubTree", 5731c8fba97SJames Feist "/xyz/openbmc_project/inventory", 0, interfaces); 5747e860f15SJohn Edward Broadbent }); 5751c8fba97SJames Feist } 576dd99e04bSP.K. Lee 5778d1b46d7Szhanghch05 inline void 5788d1b46d7Szhanghch05 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 579dd99e04bSP.K. Lee { 580c3b3c92aSVijay Khemka const char* busName = "xyz.openbmc_project.ObjectMapper"; 581c3b3c92aSVijay Khemka const char* path = "/xyz/openbmc_project/object_mapper"; 582c3b3c92aSVijay Khemka const char* interface = "xyz.openbmc_project.ObjectMapper"; 583c3b3c92aSVijay Khemka const char* method = "GetSubTreePaths"; 584c3b3c92aSVijay Khemka 585c3b3c92aSVijay Khemka const std::array<const char*, 1> interfaces = { 586c3b3c92aSVijay Khemka "xyz.openbmc_project.State.Chassis"}; 587c3b3c92aSVijay Khemka 588c3b3c92aSVijay Khemka // Use mapper to get subtree paths. 589c3b3c92aSVijay Khemka crow::connections::systemBus->async_method_call( 590b9d36b47SEd Tanous [asyncResp]( 591b9d36b47SEd Tanous const boost::system::error_code ec, 592b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& chassisList) { 593c3b3c92aSVijay Khemka if (ec) 594c3b3c92aSVijay Khemka { 595c3b3c92aSVijay Khemka BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec; 596c3b3c92aSVijay Khemka messages::internalError(asyncResp->res); 597c3b3c92aSVijay Khemka return; 598c3b3c92aSVijay Khemka } 599c3b3c92aSVijay Khemka 600dd99e04bSP.K. Lee const char* processName = "xyz.openbmc_project.State.Chassis"; 601dd99e04bSP.K. Lee const char* interfaceName = "xyz.openbmc_project.State.Chassis"; 602dd99e04bSP.K. Lee const char* destProperty = "RequestedPowerTransition"; 603dd99e04bSP.K. Lee const std::string propertyValue = 604dd99e04bSP.K. Lee "xyz.openbmc_project.State.Chassis.Transition.PowerCycle"; 605002d39b4SEd Tanous std::string objectPath = "/xyz/openbmc_project/state/chassis_system0"; 606c3b3c92aSVijay Khemka 607c3b3c92aSVijay Khemka /* Look for system reset chassis path */ 608002d39b4SEd Tanous if ((std::find(chassisList.begin(), chassisList.end(), objectPath)) == 609002d39b4SEd Tanous chassisList.end()) 610c3b3c92aSVijay Khemka { 611c3b3c92aSVijay Khemka /* We prefer to reset the full chassis_system, but if it doesn't 612c3b3c92aSVijay Khemka * exist on some platforms, fall back to a host-only power reset 613c3b3c92aSVijay Khemka */ 614c3b3c92aSVijay Khemka objectPath = "/xyz/openbmc_project/state/chassis0"; 615c3b3c92aSVijay Khemka } 616dd99e04bSP.K. Lee 617dd99e04bSP.K. Lee crow::connections::systemBus->async_method_call( 618dd99e04bSP.K. Lee [asyncResp](const boost::system::error_code ec) { 619dd99e04bSP.K. Lee // Use "Set" method to set the property value. 620dd99e04bSP.K. Lee if (ec) 621dd99e04bSP.K. Lee { 622002d39b4SEd Tanous BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: " << ec; 623dd99e04bSP.K. Lee messages::internalError(asyncResp->res); 624dd99e04bSP.K. Lee return; 625dd99e04bSP.K. Lee } 626dd99e04bSP.K. Lee 627dd99e04bSP.K. Lee messages::success(asyncResp->res); 628dd99e04bSP.K. Lee }, 629002d39b4SEd Tanous processName, objectPath, "org.freedesktop.DBus.Properties", "Set", 630002d39b4SEd Tanous interfaceName, destProperty, 631168e20c1SEd Tanous dbus::utility::DbusVariantType{propertyValue}); 632c3b3c92aSVijay Khemka }, 633c3b3c92aSVijay Khemka busName, path, interface, method, "/", 0, interfaces); 634dd99e04bSP.K. Lee } 635dd99e04bSP.K. Lee 636dd99e04bSP.K. Lee /** 637dd99e04bSP.K. Lee * ChassisResetAction class supports the POST method for the Reset 638dd99e04bSP.K. Lee * action. 639dd99e04bSP.K. Lee * Function handles POST method request. 640dd99e04bSP.K. Lee * Analyzes POST body before sending Reset request data to D-Bus. 641dd99e04bSP.K. Lee */ 6427e860f15SJohn Edward Broadbent 6437e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetAction(App& app) 644dd99e04bSP.K. Lee { 6457e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/") 646ed398213SEd Tanous .privileges(redfish::privileges::postChassis) 6477e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 64845ca1b86SEd Tanous [&app](const crow::Request& req, 6497e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6507e860f15SJohn Edward Broadbent const std::string&) { 65145ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 65245ca1b86SEd Tanous { 65345ca1b86SEd Tanous return; 65445ca1b86SEd Tanous } 655dd99e04bSP.K. Lee BMCWEB_LOG_DEBUG << "Post Chassis Reset."; 656dd99e04bSP.K. Lee 657dd99e04bSP.K. Lee std::string resetType; 658dd99e04bSP.K. Lee 65915ed6780SWilly Tu if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", 6607e860f15SJohn Edward Broadbent resetType)) 661dd99e04bSP.K. Lee { 662dd99e04bSP.K. Lee return; 663dd99e04bSP.K. Lee } 664dd99e04bSP.K. Lee 665dd99e04bSP.K. Lee if (resetType != "PowerCycle") 666dd99e04bSP.K. Lee { 667dd99e04bSP.K. Lee BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: " 668dd99e04bSP.K. Lee << resetType; 669002d39b4SEd Tanous messages::actionParameterNotSupported(asyncResp->res, resetType, 670002d39b4SEd Tanous "ResetType"); 671dd99e04bSP.K. Lee 672dd99e04bSP.K. Lee return; 673dd99e04bSP.K. Lee } 674dd99e04bSP.K. Lee doChassisPowerCycle(asyncResp); 6757e860f15SJohn Edward Broadbent }); 676dd99e04bSP.K. Lee } 6771cb1a9e6SAppaRao Puli 6781cb1a9e6SAppaRao Puli /** 6791cb1a9e6SAppaRao Puli * ChassisResetActionInfo derived class for delivering Chassis 6801cb1a9e6SAppaRao Puli * ResetType AllowableValues using ResetInfo schema. 6811cb1a9e6SAppaRao Puli */ 6827e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetActionInfo(App& app) 6831cb1a9e6SAppaRao Puli { 6847e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/") 685ed398213SEd Tanous .privileges(redfish::privileges::getActionInfo) 6867e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 68745ca1b86SEd Tanous [&app](const crow::Request& req, 6887e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 68945ca1b86SEd Tanous const std::string& chassisId) { 69045ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 6911cb1a9e6SAppaRao Puli { 69245ca1b86SEd Tanous return; 69345ca1b86SEd Tanous } 6941476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 6951476687dSEd Tanous "#ActionInfo.v1_1_2.ActionInfo"; 6961476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 6971476687dSEd Tanous "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"; 6981476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 6991476687dSEd Tanous 7001476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 701*5b9e95a1SNan Zhou nlohmann::json::array_t parameters; 702*5b9e95a1SNan Zhou nlohmann::json::object_t parameter; 703*5b9e95a1SNan Zhou parameter["Name"] = "ResetType"; 704*5b9e95a1SNan Zhou parameter["Required"] = true; 705*5b9e95a1SNan Zhou parameter["DataType"] = "String"; 7061476687dSEd Tanous nlohmann::json::array_t allowed; 7071476687dSEd Tanous allowed.push_back("PowerCycle"); 708*5b9e95a1SNan Zhou parameter["AllowableValues"] = std::move(allowed); 709*5b9e95a1SNan Zhou parameters.push_back(std::move(parameter)); 710*5b9e95a1SNan Zhou 7111476687dSEd Tanous asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 7127e860f15SJohn Edward Broadbent }); 7131cb1a9e6SAppaRao Puli } 7141cb1a9e6SAppaRao Puli 715e37f8451SRapkiewicz, Pawel } // namespace redfish 716