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" 20cf7eba09SNan Zhou #include "utils/json_utils.hpp" 211abe55efSEd Tanous 227e860f15SJohn Edward Broadbent #include <app.hpp> 23168e20c1SEd Tanous #include <dbus_utility.hpp> 2445ca1b86SEd Tanous #include <query.hpp> 25ed398213SEd Tanous #include <registries/privilege_registry.hpp> 261e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp> 2702f6ff19SGunnar Mills #include <utils/collection.hpp> 281214b7e7SGunnar Mills 291abe55efSEd Tanous namespace redfish 301abe55efSEd Tanous { 31e37f8451SRapkiewicz, Pawel 32e37f8451SRapkiewicz, Pawel /** 33beeca0aeSGunnar Mills * @brief Retrieves chassis state properties over dbus 34beeca0aeSGunnar Mills * 35beeca0aeSGunnar Mills * @param[in] aResp - Shared pointer for completing asynchronous calls. 36beeca0aeSGunnar Mills * 37beeca0aeSGunnar Mills * @return None. 38beeca0aeSGunnar Mills */ 398d1b46d7Szhanghch05 inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp) 40beeca0aeSGunnar Mills { 411e1e598dSJonathan Doman // crow::connections::systemBus->async_method_call( 421e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 431e1e598dSJonathan Doman *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis", 441e1e598dSJonathan Doman "/xyz/openbmc_project/state/chassis0", 451e1e598dSJonathan Doman "xyz.openbmc_project.State.Chassis", "CurrentPowerState", 461e1e598dSJonathan Doman [aResp{std::move(aResp)}](const boost::system::error_code ec, 471e1e598dSJonathan Doman const std::string& chassisState) { 48beeca0aeSGunnar Mills if (ec) 49beeca0aeSGunnar Mills { 50a6e5e0abSCarson Labrado if (ec == boost::system::errc::host_unreachable) 51a6e5e0abSCarson Labrado { 52a6e5e0abSCarson Labrado // Service not available, no error, just don't return 53a6e5e0abSCarson Labrado // chassis state info 54a6e5e0abSCarson Labrado BMCWEB_LOG_DEBUG << "Service not available " << ec; 55a6e5e0abSCarson Labrado return; 56a6e5e0abSCarson Labrado } 57beeca0aeSGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 58beeca0aeSGunnar Mills messages::internalError(aResp->res); 59beeca0aeSGunnar Mills return; 60beeca0aeSGunnar Mills } 61beeca0aeSGunnar Mills 621e1e598dSJonathan Doman BMCWEB_LOG_DEBUG << "Chassis state: " << chassisState; 63beeca0aeSGunnar Mills // Verify Chassis State 64002d39b4SEd Tanous if (chassisState == "xyz.openbmc_project.State.Chassis.PowerState.On") 65beeca0aeSGunnar Mills { 66beeca0aeSGunnar Mills aResp->res.jsonValue["PowerState"] = "On"; 67beeca0aeSGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Enabled"; 68beeca0aeSGunnar Mills } 691e1e598dSJonathan Doman else if (chassisState == 70beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis.PowerState.Off") 71beeca0aeSGunnar Mills { 72beeca0aeSGunnar Mills aResp->res.jsonValue["PowerState"] = "Off"; 73beeca0aeSGunnar Mills aResp->res.jsonValue["Status"]["State"] = "StandbyOffline"; 74beeca0aeSGunnar Mills } 751e1e598dSJonathan Doman }); 76beeca0aeSGunnar Mills } 77beeca0aeSGunnar Mills 788d1b46d7Szhanghch05 inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp, 79c181942fSQiang XU const std::string& service, 80c181942fSQiang XU const std::string& objPath) 81c181942fSQiang XU { 82c181942fSQiang XU BMCWEB_LOG_DEBUG << "Get intrusion status by service \n"; 83c181942fSQiang XU 841e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 851e1e598dSJonathan Doman *crow::connections::systemBus, service, objPath, 861e1e598dSJonathan Doman "xyz.openbmc_project.Chassis.Intrusion", "Status", 87c181942fSQiang XU [aResp{std::move(aResp)}](const boost::system::error_code ec, 881e1e598dSJonathan Doman const std::string& value) { 89c181942fSQiang XU if (ec) 90c181942fSQiang XU { 914e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 92c181942fSQiang XU // mandatory property 93c181942fSQiang XU BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n"; 94c181942fSQiang XU return; 95c181942fSQiang XU } 96c181942fSQiang XU 97002d39b4SEd Tanous aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensorNumber"] = 1; 981476687dSEd Tanous aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensor"] = value; 991e1e598dSJonathan Doman }); 100c181942fSQiang XU } 101c181942fSQiang XU 102c181942fSQiang XU /** 103c181942fSQiang XU * Retrieves physical security properties over dbus 104c181942fSQiang XU */ 1058d1b46d7Szhanghch05 inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp) 106c181942fSQiang XU { 107c181942fSQiang XU crow::connections::systemBus->async_method_call( 108c181942fSQiang XU [aResp{std::move(aResp)}]( 109c181942fSQiang XU const boost::system::error_code ec, 110b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 111c181942fSQiang XU if (ec) 112c181942fSQiang XU { 1134e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 114c181942fSQiang XU // mandatory property 115002d39b4SEd Tanous BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec << "\n"; 116c181942fSQiang XU return; 117c181942fSQiang XU } 118c181942fSQiang XU // Iterate over all retrieved ObjectPaths. 119c181942fSQiang XU for (const auto& object : subtree) 120c181942fSQiang XU { 121c181942fSQiang XU for (const auto& service : object.second) 122c181942fSQiang XU { 123c181942fSQiang XU getIntrusionByService(aResp, service.first, object.first); 124c181942fSQiang XU return; 125c181942fSQiang XU } 126c181942fSQiang XU } 127c181942fSQiang XU }, 128c181942fSQiang XU "xyz.openbmc_project.ObjectMapper", 129c181942fSQiang XU "/xyz/openbmc_project/object_mapper", 130c181942fSQiang XU "xyz.openbmc_project.ObjectMapper", "GetSubTree", 131271584abSEd Tanous "/xyz/openbmc_project/Intrusion", 1, 132c181942fSQiang XU std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"}); 133c181942fSQiang XU } 134c181942fSQiang XU 135cf7eba09SNan Zhou inline void handleChassisCollectionGet( 136cf7eba09SNan Zhou App& app, const crow::Request& req, 137cf7eba09SNan Zhou const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1381abe55efSEd Tanous { 1393ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 14045ca1b86SEd Tanous { 14145ca1b86SEd Tanous return; 14245ca1b86SEd Tanous } 1438d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1448d1b46d7Szhanghch05 "#ChassisCollection.ChassisCollection"; 1458d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 1468d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 147e37f8451SRapkiewicz, Pawel 14802f6ff19SGunnar Mills collection_util::getCollectionMembers( 14902f6ff19SGunnar Mills asyncResp, "/redfish/v1/Chassis", 15002f6ff19SGunnar Mills {"xyz.openbmc_project.Inventory.Item.Board", 15102f6ff19SGunnar Mills "xyz.openbmc_project.Inventory.Item.Chassis"}); 152cf7eba09SNan Zhou } 153cf7eba09SNan Zhou 154cf7eba09SNan Zhou /** 155cf7eba09SNan Zhou * ChassisCollection derived class for delivering Chassis Collection Schema 156cf7eba09SNan Zhou * Functions triggers appropriate requests on DBus 157cf7eba09SNan Zhou */ 158cf7eba09SNan Zhou inline void requestRoutesChassisCollection(App& app) 159cf7eba09SNan Zhou { 160cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/") 161cf7eba09SNan Zhou .privileges(redfish::privileges::getChassisCollection) 162cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 163cf7eba09SNan Zhou std::bind_front(handleChassisCollectionGet, std::ref(app))); 16462d5e2e4SEd Tanous } 165e37f8451SRapkiewicz, Pawel 166308f70c7SWilly Tu inline void 167308f70c7SWilly Tu getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 168308f70c7SWilly Tu const std::string& connectionName, 169308f70c7SWilly Tu const std::string& path) 170308f70c7SWilly Tu { 1711e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 1721e1e598dSJonathan Doman *crow::connections::systemBus, connectionName, path, 1731e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 174308f70c7SWilly Tu [asyncResp](const boost::system::error_code ec, 1751e1e598dSJonathan Doman const std::string& property) { 176308f70c7SWilly Tu if (ec) 177308f70c7SWilly Tu { 1780fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "DBUS response error for Location"; 179308f70c7SWilly Tu messages::internalError(asyncResp->res); 180308f70c7SWilly Tu return; 181308f70c7SWilly Tu } 182308f70c7SWilly Tu 183002d39b4SEd Tanous asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 1841e1e598dSJonathan Doman property; 1851e1e598dSJonathan Doman }); 186308f70c7SWilly Tu } 187308f70c7SWilly Tu 188308f70c7SWilly Tu inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 189308f70c7SWilly Tu const std::string& connectionName, 190308f70c7SWilly Tu const std::string& path) 191308f70c7SWilly Tu { 1921e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 1931e1e598dSJonathan Doman *crow::connections::systemBus, connectionName, path, 1941e1e598dSJonathan Doman "xyz.openbmc_project.Common.UUID", "UUID", 195308f70c7SWilly Tu [asyncResp](const boost::system::error_code ec, 1961e1e598dSJonathan Doman const std::string& chassisUUID) { 197308f70c7SWilly Tu if (ec) 198308f70c7SWilly Tu { 1990fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "DBUS response error for UUID"; 200308f70c7SWilly Tu messages::internalError(asyncResp->res); 201308f70c7SWilly Tu return; 202308f70c7SWilly Tu } 2031e1e598dSJonathan Doman asyncResp->res.jsonValue["UUID"] = chassisUUID; 2041e1e598dSJonathan Doman }); 205308f70c7SWilly Tu } 206308f70c7SWilly Tu 207cf7eba09SNan Zhou inline void 208cf7eba09SNan Zhou handleChassisGet(App& app, const crow::Request& req, 20945ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 210cf7eba09SNan Zhou const std::string& chassisId) 211cf7eba09SNan Zhou { 2123ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 21345ca1b86SEd Tanous { 21445ca1b86SEd Tanous return; 21545ca1b86SEd Tanous } 216adc4f0dbSShawn McCarney const std::array<const char*, 2> interfaces = { 217734bfe90SGunnar Mills "xyz.openbmc_project.Inventory.Item.Board", 218adc4f0dbSShawn McCarney "xyz.openbmc_project.Inventory.Item.Chassis"}; 219734bfe90SGunnar Mills 22055c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 22162d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 22262d5e2e4SEd Tanous const boost::system::error_code ec, 223b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 22462d5e2e4SEd Tanous if (ec) 2251abe55efSEd Tanous { 226f12894f8SJason M. Bills messages::internalError(asyncResp->res); 227daf36e2eSEd Tanous return; 228daf36e2eSEd Tanous } 229daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 230cf7eba09SNan Zhou for (const std::pair< 231cf7eba09SNan Zhou std::string, 232cf7eba09SNan Zhou std::vector<std::pair<std::string, std::vector<std::string>>>>& 2331214b7e7SGunnar Mills object : subtree) 2341abe55efSEd Tanous { 235daf36e2eSEd Tanous const std::string& path = object.first; 236cf7eba09SNan Zhou const std::vector<std::pair<std::string, std::vector<std::string>>>& 2371214b7e7SGunnar Mills connectionNames = object.second; 2387e860f15SJohn Edward Broadbent 239997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 240997093ebSGeorge Liu if (objPath.filename() != chassisId) 2411abe55efSEd Tanous { 242daf36e2eSEd Tanous continue; 243daf36e2eSEd Tanous } 24426f03899SShawn McCarney 245002d39b4SEd Tanous auto health = std::make_shared<HealthPopulate>(asyncResp); 246b49ac873SJames Feist 2471e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::vector<std::string>>( 2481e1e598dSJonathan Doman *crow::connections::systemBus, 249002d39b4SEd Tanous "xyz.openbmc_project.ObjectMapper", path + "/all_sensors", 2501e1e598dSJonathan Doman "xyz.openbmc_project.Association", "endpoints", 251168e20c1SEd Tanous [health](const boost::system::error_code ec2, 2521e1e598dSJonathan Doman const std::vector<std::string>& resp) { 25323a21a1cSEd Tanous if (ec2) 254b49ac873SJames Feist { 255b49ac873SJames Feist return; // no sensors = no failures 256b49ac873SJames Feist } 2571e1e598dSJonathan Doman health->inventory = resp; 2581e1e598dSJonathan Doman }); 259b49ac873SJames Feist 260b49ac873SJames Feist health->populate(); 261b49ac873SJames Feist 26226f6976fSEd Tanous if (connectionNames.empty()) 2631abe55efSEd Tanous { 2641c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 265e0d918bcSEd Tanous continue; 266daf36e2eSEd Tanous } 267e0d918bcSEd Tanous 26849c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.type"] = 2695ac5a2f4SGunnar Mills "#Chassis.v1_16_0.Chassis"; 27049c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.id"] = 27149c53ac9SJohnathan Mantey "/redfish/v1/Chassis/" + chassisId; 27249c53ac9SJohnathan Mantey asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 27349c53ac9SJohnathan Mantey asyncResp->res.jsonValue["ChassisType"] = "RackMount"; 274cf7eba09SNan Zhou asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]["target"] = 275cf7eba09SNan Zhou "/redfish/v1/Chassis/" + chassisId + "/Actions/Chassis.Reset"; 2761476687dSEd Tanous asyncResp->res 277cf7eba09SNan Zhou .jsonValue["Actions"]["#Chassis.Reset"]["@Redfish.ActionInfo"] = 278002d39b4SEd Tanous "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"; 2791476687dSEd Tanous asyncResp->res.jsonValue["PCIeDevices"]["@odata.id"] = 2801476687dSEd Tanous "/redfish/v1/Systems/system/PCIeDevices"; 28149c53ac9SJohnathan Mantey 28292903bd4SJohn Edward Broadbent sdbusplus::asio::getProperty<std::vector<std::string>>( 28392903bd4SJohn Edward Broadbent *crow::connections::systemBus, 28492903bd4SJohn Edward Broadbent "xyz.openbmc_project.ObjectMapper", path + "/drive", 28592903bd4SJohn Edward Broadbent "xyz.openbmc_project.Association", "endpoints", 286cf7eba09SNan Zhou [asyncResp, chassisId](const boost::system::error_code ec3, 28792903bd4SJohn Edward Broadbent const std::vector<std::string>& resp) { 28892903bd4SJohn Edward Broadbent if (ec3 || resp.empty()) 28992903bd4SJohn Edward Broadbent { 29092903bd4SJohn Edward Broadbent return; // no drives = no failures 29192903bd4SJohn Edward Broadbent } 29292903bd4SJohn Edward Broadbent 29392903bd4SJohn Edward Broadbent nlohmann::json reference; 294*a0cb40cbSJohn Edward Broadbent reference["@odata.id"] = crow::utility::urlFromPieces( 29592903bd4SJohn Edward Broadbent "redfish", "v1", "Chassis", chassisId, "Drives"); 29692903bd4SJohn Edward Broadbent asyncResp->res.jsonValue["Drives"] = std::move(reference); 29792903bd4SJohn Edward Broadbent }); 29892903bd4SJohn Edward Broadbent 299002d39b4SEd Tanous const std::string& connectionName = connectionNames[0].first; 3001c8fba97SJames Feist 30123a21a1cSEd Tanous const std::vector<std::string>& interfaces2 = 3021c8fba97SJames Feist connectionNames[0].second; 3031c8fba97SJames Feist const std::array<const char*, 2> hasIndicatorLed = { 3041c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 3050fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 3061c8fba97SJames Feist 307476b9cc5STejas Patil const std::string assetTagInterface = 3080fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.AssetTag"; 309476b9cc5STejas Patil if (std::find(interfaces2.begin(), interfaces2.end(), 310476b9cc5STejas Patil assetTagInterface) != interfaces2.end()) 311476b9cc5STejas Patil { 3121e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 313002d39b4SEd Tanous *crow::connections::systemBus, connectionName, path, 314002d39b4SEd Tanous assetTagInterface, "AssetTag", 315476b9cc5STejas Patil [asyncResp, chassisId(std::string(chassisId))]( 3168a592810SEd Tanous const boost::system::error_code ec2, 3171e1e598dSJonathan Doman const std::string& property) { 3188a592810SEd Tanous if (ec2) 319476b9cc5STejas Patil { 320cf7eba09SNan Zhou BMCWEB_LOG_DEBUG << "DBus response error for AssetTag"; 321476b9cc5STejas Patil messages::internalError(asyncResp->res); 322476b9cc5STejas Patil return; 323476b9cc5STejas Patil } 324002d39b4SEd Tanous asyncResp->res.jsonValue["AssetTag"] = property; 3251e1e598dSJonathan Doman }); 326476b9cc5STejas Patil } 327476b9cc5STejas Patil 3281c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 3291c8fba97SJames Feist { 330002d39b4SEd Tanous if (std::find(interfaces2.begin(), interfaces2.end(), 33123a21a1cSEd Tanous interface) != interfaces2.end()) 3321c8fba97SJames Feist { 3331c8fba97SJames Feist getIndicatorLedState(asyncResp); 3349f8bfa7cSGunnar Mills getLocationIndicatorActive(asyncResp); 3351c8fba97SJames Feist break; 3361c8fba97SJames Feist } 3371c8fba97SJames Feist } 3381c8fba97SJames Feist 33955c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 34062d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 34190728b54SEd Tanous const boost::system::error_code /*ec2*/, 342cf7eba09SNan Zhou const dbus::utility::DBusPropertiesMap& propertiesList) { 343002d39b4SEd Tanous for (const std::pair<std::string, 344cf7eba09SNan Zhou dbus::utility::DbusVariantType>& property : 345cf7eba09SNan Zhou propertiesList) 3461abe55efSEd Tanous { 3477e860f15SJohn Edward Broadbent // Store DBus properties that are also 3487e860f15SJohn Edward Broadbent // Redfish properties with same name and a 3497e860f15SJohn Edward Broadbent // string value 350002d39b4SEd Tanous const std::string& propertyName = property.first; 35199cffd7fSShawn McCarney if ((propertyName == "PartNumber") || 35299cffd7fSShawn McCarney (propertyName == "SerialNumber") || 35399cffd7fSShawn McCarney (propertyName == "Manufacturer") || 354caa11f7aSAlpana Kumari (propertyName == "Model") || 355caa11f7aSAlpana Kumari (propertyName == "SparePartNumber")) 35699cffd7fSShawn McCarney { 357daf36e2eSEd Tanous const std::string* value = 358002d39b4SEd Tanous std::get_if<std::string>(&property.second); 359caa11f7aSAlpana Kumari if (value == nullptr) 3601abe55efSEd Tanous { 361002d39b4SEd Tanous BMCWEB_LOG_ERROR << "Null value returned for " 362caa11f7aSAlpana Kumari << propertyName; 363002d39b4SEd Tanous messages::internalError(asyncResp->res); 364caa11f7aSAlpana Kumari return; 365daf36e2eSEd Tanous } 366caa11f7aSAlpana Kumari // SparePartNumber is optional on D-Bus 367caa11f7aSAlpana Kumari // so skip if it is empty 368caa11f7aSAlpana Kumari if (propertyName == "SparePartNumber") 369caa11f7aSAlpana Kumari { 37026f6976fSEd Tanous if (value->empty()) 371caa11f7aSAlpana Kumari { 372caa11f7aSAlpana Kumari continue; 373caa11f7aSAlpana Kumari } 374caa11f7aSAlpana Kumari } 375002d39b4SEd Tanous asyncResp->res.jsonValue[propertyName] = *value; 376daf36e2eSEd Tanous } 37799cffd7fSShawn McCarney } 37862d5e2e4SEd Tanous asyncResp->res.jsonValue["Name"] = chassisId; 37962d5e2e4SEd Tanous asyncResp->res.jsonValue["Id"] = chassisId; 3800256b694Szhanghch05 #ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL 381002d39b4SEd Tanous asyncResp->res.jsonValue["Thermal"]["@odata.id"] = 382002d39b4SEd Tanous "/redfish/v1/Chassis/" + chassisId + "/Thermal"; 3832474adfaSEd Tanous // Power object 3841476687dSEd Tanous asyncResp->res.jsonValue["Power"]["@odata.id"] = 385002d39b4SEd Tanous "/redfish/v1/Chassis/" + chassisId + "/Power"; 3860256b694Szhanghch05 #endif 3872973963eSXiaochao Ma #ifdef BMCWEB_NEW_POWERSUBSYSTEM_THERMALSUBSYSTEM 3882973963eSXiaochao Ma asyncResp->res.jsonValue["ThermalSubsystem"]["@odata.id"] = 3892973963eSXiaochao Ma crow::utility::urlFromPieces("redfish", "v1", "Chassis", 3902973963eSXiaochao Ma chassisId, "ThermalSubsystem"); 3912973963eSXiaochao Ma #endif 39295a3ecadSAnthony Wilson // SensorCollection 393002d39b4SEd Tanous asyncResp->res.jsonValue["Sensors"]["@odata.id"] = 394002d39b4SEd Tanous "/redfish/v1/Chassis/" + chassisId + "/Sensors"; 395002d39b4SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 3961476687dSEd Tanous 3971476687dSEd Tanous nlohmann::json::array_t computerSystems; 3981476687dSEd Tanous nlohmann::json::object_t system; 399002d39b4SEd Tanous system["@odata.id"] = "/redfish/v1/Systems/system"; 4001476687dSEd Tanous computerSystems.push_back(std::move(system)); 401002d39b4SEd Tanous asyncResp->res.jsonValue["Links"]["ComputerSystems"] = 4021476687dSEd Tanous std::move(computerSystems); 4031476687dSEd Tanous 4041476687dSEd Tanous nlohmann::json::array_t managedBy; 4051476687dSEd Tanous nlohmann::json::object_t manager; 406002d39b4SEd Tanous manager["@odata.id"] = "/redfish/v1/Managers/bmc"; 4071476687dSEd Tanous managedBy.push_back(std::move(manager)); 4087e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Links"]["ManagedBy"] = 4091476687dSEd Tanous std::move(managedBy); 410beeca0aeSGunnar Mills getChassisState(asyncResp); 411daf36e2eSEd Tanous }, 412002d39b4SEd Tanous connectionName, path, "org.freedesktop.DBus.Properties", 413002d39b4SEd Tanous "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset"); 4142c37b4b0SSharad Yadav 415308f70c7SWilly Tu for (const auto& interface : interfaces2) 4162c37b4b0SSharad Yadav { 417308f70c7SWilly Tu if (interface == "xyz.openbmc_project.Common.UUID") 4182c37b4b0SSharad Yadav { 419308f70c7SWilly Tu getChassisUUID(asyncResp, connectionName, path); 4202c37b4b0SSharad Yadav } 421cf7eba09SNan Zhou else if (interface == 4220fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 4232c37b4b0SSharad Yadav { 424002d39b4SEd Tanous getChassisLocationCode(asyncResp, connectionName, path); 4252c37b4b0SSharad Yadav } 4262c37b4b0SSharad Yadav } 4272c37b4b0SSharad Yadav 428daf36e2eSEd Tanous return; 429daf36e2eSEd Tanous } 430e0d918bcSEd Tanous 431daf36e2eSEd Tanous // Couldn't find an object with that name. return an error 432cf7eba09SNan Zhou messages::resourceNotFound(asyncResp->res, "#Chassis.v1_16_0.Chassis", 433cf7eba09SNan Zhou chassisId); 434daf36e2eSEd Tanous }, 435daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", 436daf36e2eSEd Tanous "/xyz/openbmc_project/object_mapper", 437daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTree", 438271584abSEd Tanous "/xyz/openbmc_project/inventory", 0, interfaces); 439c181942fSQiang XU 440c181942fSQiang XU getPhysicalSecurityData(asyncResp); 441cf7eba09SNan Zhou } 4421c8fba97SJames Feist 443cf7eba09SNan Zhou inline void 444cf7eba09SNan Zhou handleChassisPatch(App& app, const crow::Request& req, 4457e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 446cf7eba09SNan Zhou const std::string& param) 447cf7eba09SNan Zhou { 4483ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 44945ca1b86SEd Tanous { 45045ca1b86SEd Tanous return; 45145ca1b86SEd Tanous } 4529f8bfa7cSGunnar Mills std::optional<bool> locationIndicatorActive; 4531c8fba97SJames Feist std::optional<std::string> indicatorLed; 4541c8fba97SJames Feist 4557e860f15SJohn Edward Broadbent if (param.empty()) 4561c8fba97SJames Feist { 4571c8fba97SJames Feist return; 4581c8fba97SJames Feist } 4591c8fba97SJames Feist 46015ed6780SWilly Tu if (!json_util::readJsonPatch( 4617e860f15SJohn Edward Broadbent req, asyncResp->res, "LocationIndicatorActive", 4627e860f15SJohn Edward Broadbent locationIndicatorActive, "IndicatorLED", indicatorLed)) 4631c8fba97SJames Feist { 4641c8fba97SJames Feist return; 4651c8fba97SJames Feist } 4661c8fba97SJames Feist 4679f8bfa7cSGunnar Mills // TODO (Gunnar): Remove IndicatorLED after enough time has passed 4689f8bfa7cSGunnar Mills if (!locationIndicatorActive && !indicatorLed) 4691c8fba97SJames Feist { 4701c8fba97SJames Feist return; // delete this when we support more patch properties 4711c8fba97SJames Feist } 472d6aa0093SGunnar Mills if (indicatorLed) 473d6aa0093SGunnar Mills { 4747e860f15SJohn Edward Broadbent asyncResp->res.addHeader( 4757e860f15SJohn Edward Broadbent boost::beast::http::field::warning, 4760fda0f12SGeorge Liu "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\""); 477d6aa0093SGunnar Mills } 4781c8fba97SJames Feist 4791c8fba97SJames Feist const std::array<const char*, 2> interfaces = { 4801c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board", 4811c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Chassis"}; 4821c8fba97SJames Feist 4837e860f15SJohn Edward Broadbent const std::string& chassisId = param; 4841c8fba97SJames Feist 4851c8fba97SJames Feist crow::connections::systemBus->async_method_call( 486cf7eba09SNan Zhou [asyncResp, chassisId, locationIndicatorActive, 487cf7eba09SNan Zhou indicatorLed](const boost::system::error_code ec, 488b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 4891c8fba97SJames Feist if (ec) 4901c8fba97SJames Feist { 4911c8fba97SJames Feist messages::internalError(asyncResp->res); 4921c8fba97SJames Feist return; 4931c8fba97SJames Feist } 4941c8fba97SJames Feist 4951c8fba97SJames Feist // Iterate over all retrieved ObjectPaths. 496cf7eba09SNan Zhou for (const std::pair< 497cf7eba09SNan Zhou std::string, 498cf7eba09SNan Zhou std::vector<std::pair<std::string, std::vector<std::string>>>>& 4991214b7e7SGunnar Mills object : subtree) 5001c8fba97SJames Feist { 5011c8fba97SJames Feist const std::string& path = object.first; 502cf7eba09SNan Zhou const std::vector<std::pair<std::string, std::vector<std::string>>>& 5031214b7e7SGunnar Mills connectionNames = object.second; 5041c8fba97SJames Feist 505997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 506997093ebSGeorge Liu if (objPath.filename() != chassisId) 5071c8fba97SJames Feist { 5081c8fba97SJames Feist continue; 5091c8fba97SJames Feist } 5101c8fba97SJames Feist 51126f6976fSEd Tanous if (connectionNames.empty()) 5121c8fba97SJames Feist { 5131c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 5141c8fba97SJames Feist continue; 5151c8fba97SJames Feist } 5161c8fba97SJames Feist 51723a21a1cSEd Tanous const std::vector<std::string>& interfaces3 = 5181c8fba97SJames Feist connectionNames[0].second; 5191c8fba97SJames Feist 5201c8fba97SJames Feist const std::array<const char*, 2> hasIndicatorLed = { 5211c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 5220fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 5231c8fba97SJames Feist bool indicatorChassis = false; 5241c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 5251c8fba97SJames Feist { 526002d39b4SEd Tanous if (std::find(interfaces3.begin(), interfaces3.end(), 52723a21a1cSEd Tanous interface) != interfaces3.end()) 5281c8fba97SJames Feist { 5291c8fba97SJames Feist indicatorChassis = true; 5301c8fba97SJames Feist break; 5311c8fba97SJames Feist } 5321c8fba97SJames Feist } 5339f8bfa7cSGunnar Mills if (locationIndicatorActive) 5349f8bfa7cSGunnar Mills { 5359f8bfa7cSGunnar Mills if (indicatorChassis) 5369f8bfa7cSGunnar Mills { 537002d39b4SEd Tanous setLocationIndicatorActive(asyncResp, 538002d39b4SEd Tanous *locationIndicatorActive); 5399f8bfa7cSGunnar Mills } 5409f8bfa7cSGunnar Mills else 5419f8bfa7cSGunnar Mills { 542002d39b4SEd Tanous messages::propertyUnknown(asyncResp->res, 543002d39b4SEd Tanous "LocationIndicatorActive"); 5449f8bfa7cSGunnar Mills } 5459f8bfa7cSGunnar Mills } 5469f8bfa7cSGunnar Mills if (indicatorLed) 5479f8bfa7cSGunnar Mills { 5481c8fba97SJames Feist if (indicatorChassis) 5491c8fba97SJames Feist { 550f23b7296SEd Tanous setIndicatorLedState(asyncResp, *indicatorLed); 5511c8fba97SJames Feist } 5521c8fba97SJames Feist else 5531c8fba97SJames Feist { 554cf7eba09SNan Zhou messages::propertyUnknown(asyncResp->res, "IndicatorLED"); 5551c8fba97SJames Feist } 5561c8fba97SJames Feist } 5571c8fba97SJames Feist return; 5581c8fba97SJames Feist } 5591c8fba97SJames Feist 560cf7eba09SNan Zhou messages::resourceNotFound(asyncResp->res, "#Chassis.v1_14_0.Chassis", 561cf7eba09SNan Zhou chassisId); 5621c8fba97SJames Feist }, 5631c8fba97SJames Feist "xyz.openbmc_project.ObjectMapper", 5641c8fba97SJames Feist "/xyz/openbmc_project/object_mapper", 5651c8fba97SJames Feist "xyz.openbmc_project.ObjectMapper", "GetSubTree", 5661c8fba97SJames Feist "/xyz/openbmc_project/inventory", 0, interfaces); 567cf7eba09SNan Zhou } 568cf7eba09SNan Zhou 569cf7eba09SNan Zhou /** 570cf7eba09SNan Zhou * Chassis override class for delivering Chassis Schema 571cf7eba09SNan Zhou * Functions triggers appropriate requests on DBus 572cf7eba09SNan Zhou */ 573cf7eba09SNan Zhou inline void requestRoutesChassis(App& app) 574cf7eba09SNan Zhou { 575cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 576cf7eba09SNan Zhou .privileges(redfish::privileges::getChassis) 577cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 578cf7eba09SNan Zhou std::bind_front(handleChassisGet, std::ref(app))); 579cf7eba09SNan Zhou 580cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 581cf7eba09SNan Zhou .privileges(redfish::privileges::patchChassis) 582cf7eba09SNan Zhou .methods(boost::beast::http::verb::patch)( 583cf7eba09SNan Zhou std::bind_front(handleChassisPatch, std::ref(app))); 5841c8fba97SJames Feist } 585dd99e04bSP.K. Lee 5868d1b46d7Szhanghch05 inline void 5878d1b46d7Szhanghch05 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 588dd99e04bSP.K. Lee { 589c3b3c92aSVijay Khemka const char* busName = "xyz.openbmc_project.ObjectMapper"; 590c3b3c92aSVijay Khemka const char* path = "/xyz/openbmc_project/object_mapper"; 591c3b3c92aSVijay Khemka const char* interface = "xyz.openbmc_project.ObjectMapper"; 592c3b3c92aSVijay Khemka const char* method = "GetSubTreePaths"; 593c3b3c92aSVijay Khemka 594c3b3c92aSVijay Khemka const std::array<const char*, 1> interfaces = { 595c3b3c92aSVijay Khemka "xyz.openbmc_project.State.Chassis"}; 596c3b3c92aSVijay Khemka 597c3b3c92aSVijay Khemka // Use mapper to get subtree paths. 598c3b3c92aSVijay Khemka crow::connections::systemBus->async_method_call( 599b9d36b47SEd Tanous [asyncResp]( 600b9d36b47SEd Tanous const boost::system::error_code ec, 601b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& chassisList) { 602c3b3c92aSVijay Khemka if (ec) 603c3b3c92aSVijay Khemka { 604c3b3c92aSVijay Khemka BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec; 605c3b3c92aSVijay Khemka messages::internalError(asyncResp->res); 606c3b3c92aSVijay Khemka return; 607c3b3c92aSVijay Khemka } 608c3b3c92aSVijay Khemka 609dd99e04bSP.K. Lee const char* processName = "xyz.openbmc_project.State.Chassis"; 610dd99e04bSP.K. Lee const char* interfaceName = "xyz.openbmc_project.State.Chassis"; 611dd99e04bSP.K. Lee const char* destProperty = "RequestedPowerTransition"; 612dd99e04bSP.K. Lee const std::string propertyValue = 613dd99e04bSP.K. Lee "xyz.openbmc_project.State.Chassis.Transition.PowerCycle"; 614002d39b4SEd Tanous std::string objectPath = "/xyz/openbmc_project/state/chassis_system0"; 615c3b3c92aSVijay Khemka 616c3b3c92aSVijay Khemka /* Look for system reset chassis path */ 617002d39b4SEd Tanous if ((std::find(chassisList.begin(), chassisList.end(), objectPath)) == 618002d39b4SEd Tanous chassisList.end()) 619c3b3c92aSVijay Khemka { 620c3b3c92aSVijay Khemka /* We prefer to reset the full chassis_system, but if it doesn't 621c3b3c92aSVijay Khemka * exist on some platforms, fall back to a host-only power reset 622c3b3c92aSVijay Khemka */ 623c3b3c92aSVijay Khemka objectPath = "/xyz/openbmc_project/state/chassis0"; 624c3b3c92aSVijay Khemka } 625dd99e04bSP.K. Lee 626dd99e04bSP.K. Lee crow::connections::systemBus->async_method_call( 6278a592810SEd Tanous [asyncResp](const boost::system::error_code ec2) { 628dd99e04bSP.K. Lee // Use "Set" method to set the property value. 6298a592810SEd Tanous if (ec2) 630dd99e04bSP.K. Lee { 6318a592810SEd Tanous BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: " << ec2; 632dd99e04bSP.K. Lee messages::internalError(asyncResp->res); 633dd99e04bSP.K. Lee return; 634dd99e04bSP.K. Lee } 635dd99e04bSP.K. Lee 636dd99e04bSP.K. Lee messages::success(asyncResp->res); 637dd99e04bSP.K. Lee }, 638002d39b4SEd Tanous processName, objectPath, "org.freedesktop.DBus.Properties", "Set", 639002d39b4SEd Tanous interfaceName, destProperty, 640168e20c1SEd Tanous dbus::utility::DbusVariantType{propertyValue}); 641c3b3c92aSVijay Khemka }, 642c3b3c92aSVijay Khemka busName, path, interface, method, "/", 0, interfaces); 643dd99e04bSP.K. Lee } 644dd99e04bSP.K. Lee 645cf7eba09SNan Zhou inline void handleChassisResetActionInfoPost( 646cf7eba09SNan Zhou App& app, const crow::Request& req, 6477e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 648cf7eba09SNan Zhou const std::string& /*chassisId*/) 649cf7eba09SNan Zhou { 6503ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 65145ca1b86SEd Tanous { 65245ca1b86SEd Tanous return; 65345ca1b86SEd Tanous } 654dd99e04bSP.K. Lee BMCWEB_LOG_DEBUG << "Post Chassis Reset."; 655dd99e04bSP.K. Lee 656dd99e04bSP.K. Lee std::string resetType; 657dd99e04bSP.K. Lee 658cf7eba09SNan Zhou if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType)) 659dd99e04bSP.K. Lee { 660dd99e04bSP.K. Lee return; 661dd99e04bSP.K. Lee } 662dd99e04bSP.K. Lee 663dd99e04bSP.K. Lee if (resetType != "PowerCycle") 664dd99e04bSP.K. Lee { 665dd99e04bSP.K. Lee BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: " 666dd99e04bSP.K. Lee << resetType; 667002d39b4SEd Tanous messages::actionParameterNotSupported(asyncResp->res, resetType, 668002d39b4SEd Tanous "ResetType"); 669dd99e04bSP.K. Lee 670dd99e04bSP.K. Lee return; 671dd99e04bSP.K. Lee } 672dd99e04bSP.K. Lee doChassisPowerCycle(asyncResp); 673dd99e04bSP.K. Lee } 6741cb1a9e6SAppaRao Puli 6751cb1a9e6SAppaRao Puli /** 676cf7eba09SNan Zhou * ChassisResetAction class supports the POST method for the Reset 677cf7eba09SNan Zhou * action. 678cf7eba09SNan Zhou * Function handles POST method request. 679cf7eba09SNan Zhou * Analyzes POST body before sending Reset request data to D-Bus. 6801cb1a9e6SAppaRao Puli */ 681cf7eba09SNan Zhou 682cf7eba09SNan Zhou inline void requestRoutesChassisResetAction(App& app) 6831cb1a9e6SAppaRao Puli { 684cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/") 685cf7eba09SNan Zhou .privileges(redfish::privileges::postChassis) 686cf7eba09SNan Zhou .methods(boost::beast::http::verb::post)( 687cf7eba09SNan Zhou std::bind_front(handleChassisResetActionInfoPost, std::ref(app))); 688cf7eba09SNan Zhou } 689cf7eba09SNan Zhou 690cf7eba09SNan Zhou inline void handleChassisResetActionInfoGet( 691cf7eba09SNan Zhou App& app, const crow::Request& req, 6927e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 693cf7eba09SNan Zhou const std::string& chassisId) 694cf7eba09SNan Zhou { 6953ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 6961cb1a9e6SAppaRao Puli { 69745ca1b86SEd Tanous return; 69845ca1b86SEd Tanous } 699cf7eba09SNan Zhou asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo"; 7001476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 7011476687dSEd Tanous "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"; 7021476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 7031476687dSEd Tanous 7041476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 7055b9e95a1SNan Zhou nlohmann::json::array_t parameters; 7065b9e95a1SNan Zhou nlohmann::json::object_t parameter; 7075b9e95a1SNan Zhou parameter["Name"] = "ResetType"; 7085b9e95a1SNan Zhou parameter["Required"] = true; 7095b9e95a1SNan Zhou parameter["DataType"] = "String"; 7101476687dSEd Tanous nlohmann::json::array_t allowed; 7111476687dSEd Tanous allowed.push_back("PowerCycle"); 7125b9e95a1SNan Zhou parameter["AllowableValues"] = std::move(allowed); 7135b9e95a1SNan Zhou parameters.push_back(std::move(parameter)); 7145b9e95a1SNan Zhou 7151476687dSEd Tanous asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 716cf7eba09SNan Zhou } 717cf7eba09SNan Zhou 718cf7eba09SNan Zhou /** 719cf7eba09SNan Zhou * ChassisResetActionInfo derived class for delivering Chassis 720cf7eba09SNan Zhou * ResetType AllowableValues using ResetInfo schema. 721cf7eba09SNan Zhou */ 722cf7eba09SNan Zhou inline void requestRoutesChassisResetActionInfo(App& app) 723cf7eba09SNan Zhou { 724cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/") 725cf7eba09SNan Zhou .privileges(redfish::privileges::getActionInfo) 726cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 727cf7eba09SNan Zhou std::bind_front(handleChassisResetActionInfoGet, std::ref(app))); 7281cb1a9e6SAppaRao Puli } 7291cb1a9e6SAppaRao Puli 730e37f8451SRapkiewicz, Pawel } // namespace redfish 731