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> 23168e20c1SEd Tanous #include <dbus_utility.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 631e1e598dSJonathan Doman if (chassisState == 641e1e598dSJonathan Doman "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 78beeca0aeSGunnar Mills /** 79e37f8451SRapkiewicz, Pawel * DBus types primitives for several generic DBus interfaces 80e37f8451SRapkiewicz, Pawel * TODO(Pawel) consider move this to separate file into boost::dbus 81e37f8451SRapkiewicz, Pawel */ 82aa2e59c1SEd Tanous using ManagedObjectsType = std::vector<std::pair< 83aa2e59c1SEd Tanous sdbusplus::message::object_path, 84168e20c1SEd Tanous std::vector<std::pair< 85168e20c1SEd Tanous std::string, 86168e20c1SEd Tanous std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>>>>>; 87e37f8451SRapkiewicz, Pawel 88168e20c1SEd Tanous using PropertiesType = 89168e20c1SEd Tanous boost::container::flat_map<std::string, dbus::utility::DbusVariantType>; 90e37f8451SRapkiewicz, Pawel 918d1b46d7Szhanghch05 inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp, 92c181942fSQiang XU const std::string& service, 93c181942fSQiang XU const std::string& objPath) 94c181942fSQiang XU { 95c181942fSQiang XU BMCWEB_LOG_DEBUG << "Get intrusion status by service \n"; 96c181942fSQiang XU 971e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 981e1e598dSJonathan Doman *crow::connections::systemBus, service, objPath, 991e1e598dSJonathan Doman "xyz.openbmc_project.Chassis.Intrusion", "Status", 100c181942fSQiang XU [aResp{std::move(aResp)}](const boost::system::error_code ec, 1011e1e598dSJonathan Doman const std::string& value) { 102c181942fSQiang XU if (ec) 103c181942fSQiang XU { 1044e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 105c181942fSQiang XU // mandatory property 106c181942fSQiang XU BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n"; 107c181942fSQiang XU return; 108c181942fSQiang XU } 109c181942fSQiang XU 110c181942fSQiang XU aResp->res.jsonValue["PhysicalSecurity"] = { 1111e1e598dSJonathan Doman {"IntrusionSensorNumber", 1}, {"IntrusionSensor", value}}; 1121e1e598dSJonathan Doman }); 113c181942fSQiang XU } 114c181942fSQiang XU 115c181942fSQiang XU /** 116c181942fSQiang XU * Retrieves physical security properties over dbus 117c181942fSQiang XU */ 1188d1b46d7Szhanghch05 inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp) 119c181942fSQiang XU { 120c181942fSQiang XU crow::connections::systemBus->async_method_call( 121c181942fSQiang XU [aResp{std::move(aResp)}]( 122c181942fSQiang XU const boost::system::error_code ec, 123c181942fSQiang XU const std::vector<std::pair< 124c181942fSQiang XU std::string, 1251214b7e7SGunnar Mills std::vector<std::pair<std::string, std::vector<std::string>>>>>& 1261214b7e7SGunnar Mills subtree) { 127c181942fSQiang XU if (ec) 128c181942fSQiang XU { 1294e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 130c181942fSQiang XU // mandatory property 13154fbf177SAndrew Geissler BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec 132c181942fSQiang XU << "\n"; 133c181942fSQiang XU return; 134c181942fSQiang XU } 135c181942fSQiang XU // Iterate over all retrieved ObjectPaths. 136c181942fSQiang XU for (const auto& object : subtree) 137c181942fSQiang XU { 138c181942fSQiang XU for (const auto& service : object.second) 139c181942fSQiang XU { 140c181942fSQiang XU getIntrusionByService(aResp, service.first, object.first); 141c181942fSQiang XU return; 142c181942fSQiang XU } 143c181942fSQiang XU } 144c181942fSQiang XU }, 145c181942fSQiang XU "xyz.openbmc_project.ObjectMapper", 146c181942fSQiang XU "/xyz/openbmc_project/object_mapper", 147c181942fSQiang XU "xyz.openbmc_project.ObjectMapper", "GetSubTree", 148271584abSEd Tanous "/xyz/openbmc_project/Intrusion", 1, 149c181942fSQiang XU std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"}); 150c181942fSQiang XU } 151c181942fSQiang XU 152e37f8451SRapkiewicz, Pawel /** 153e37f8451SRapkiewicz, Pawel * ChassisCollection derived class for delivering Chassis Collection Schema 154e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 155e37f8451SRapkiewicz, Pawel */ 1567e860f15SJohn Edward Broadbent inline void requestRoutesChassisCollection(App& app) 1571abe55efSEd Tanous { 1587e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/") 159ed398213SEd Tanous .privileges(redfish::privileges::getChassisCollection) 1607e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 1617e860f15SJohn Edward Broadbent [](const crow::Request&, 1627e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1638d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1648d1b46d7Szhanghch05 "#ChassisCollection.ChassisCollection"; 1658d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 1668d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 167e37f8451SRapkiewicz, Pawel 16802f6ff19SGunnar Mills collection_util::getCollectionMembers( 16902f6ff19SGunnar Mills asyncResp, "/redfish/v1/Chassis", 17002f6ff19SGunnar Mills {"xyz.openbmc_project.Inventory.Item.Board", 17102f6ff19SGunnar Mills "xyz.openbmc_project.Inventory.Item.Chassis"}); 1727e860f15SJohn Edward Broadbent }); 17362d5e2e4SEd Tanous } 174e37f8451SRapkiewicz, Pawel 175308f70c7SWilly Tu inline void 176308f70c7SWilly Tu getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 177308f70c7SWilly Tu const std::string& connectionName, 178308f70c7SWilly Tu const std::string& path) 179308f70c7SWilly Tu { 1801e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 1811e1e598dSJonathan Doman *crow::connections::systemBus, connectionName, path, 1821e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 183308f70c7SWilly Tu [asyncResp](const boost::system::error_code ec, 1841e1e598dSJonathan Doman const std::string& property) { 185308f70c7SWilly Tu if (ec) 186308f70c7SWilly Tu { 1870fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "DBUS response error for Location"; 188308f70c7SWilly Tu messages::internalError(asyncResp->res); 189308f70c7SWilly Tu return; 190308f70c7SWilly Tu } 191308f70c7SWilly Tu 192308f70c7SWilly Tu asyncResp->res 1931e1e598dSJonathan Doman .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 1941e1e598dSJonathan Doman property; 1951e1e598dSJonathan Doman }); 196308f70c7SWilly Tu } 197308f70c7SWilly Tu 198308f70c7SWilly Tu inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 199308f70c7SWilly Tu const std::string& connectionName, 200308f70c7SWilly Tu const std::string& path) 201308f70c7SWilly Tu { 2021e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 2031e1e598dSJonathan Doman *crow::connections::systemBus, connectionName, path, 2041e1e598dSJonathan Doman "xyz.openbmc_project.Common.UUID", "UUID", 205308f70c7SWilly Tu [asyncResp](const boost::system::error_code ec, 2061e1e598dSJonathan Doman const std::string& chassisUUID) { 207308f70c7SWilly Tu if (ec) 208308f70c7SWilly Tu { 2090fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "DBUS response error for UUID"; 210308f70c7SWilly Tu messages::internalError(asyncResp->res); 211308f70c7SWilly Tu return; 212308f70c7SWilly Tu } 2131e1e598dSJonathan Doman asyncResp->res.jsonValue["UUID"] = chassisUUID; 2141e1e598dSJonathan Doman }); 215308f70c7SWilly Tu } 216308f70c7SWilly Tu 217e37f8451SRapkiewicz, Pawel /** 218e37f8451SRapkiewicz, Pawel * Chassis override class for delivering Chassis Schema 219e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 220e37f8451SRapkiewicz, Pawel */ 2217e860f15SJohn Edward Broadbent inline void requestRoutesChassis(App& app) 2221abe55efSEd Tanous { 2237e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 224ed398213SEd Tanous .privileges(redfish::privileges::getChassis) 2257e860f15SJohn Edward Broadbent .methods( 2267e860f15SJohn Edward Broadbent boost::beast::http::verb::get)([](const crow::Request&, 2277e860f15SJohn Edward Broadbent const std::shared_ptr< 2287e860f15SJohn Edward Broadbent bmcweb::AsyncResp>& asyncResp, 2297e860f15SJohn Edward Broadbent const std::string& chassisId) { 230adc4f0dbSShawn McCarney const std::array<const char*, 2> interfaces = { 231734bfe90SGunnar Mills "xyz.openbmc_project.Inventory.Item.Board", 232adc4f0dbSShawn McCarney "xyz.openbmc_project.Inventory.Item.Chassis"}; 233734bfe90SGunnar Mills 23455c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 23562d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 23662d5e2e4SEd Tanous const boost::system::error_code ec, 2371c8fba97SJames Feist const crow::openbmc_mapper::GetSubTreeType& subtree) { 23862d5e2e4SEd Tanous if (ec) 2391abe55efSEd Tanous { 240f12894f8SJason M. Bills messages::internalError(asyncResp->res); 241daf36e2eSEd Tanous return; 242daf36e2eSEd Tanous } 243daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 2441abe55efSEd Tanous for (const std::pair< 2451abe55efSEd Tanous std::string, 2467e860f15SJohn Edward Broadbent std::vector<std::pair<std::string, 2477e860f15SJohn Edward Broadbent std::vector<std::string>>>>& 2481214b7e7SGunnar Mills object : subtree) 2491abe55efSEd Tanous { 250daf36e2eSEd Tanous const std::string& path = object.first; 2511abe55efSEd Tanous const std::vector< 2521214b7e7SGunnar Mills std::pair<std::string, std::vector<std::string>>>& 2531214b7e7SGunnar Mills connectionNames = object.second; 2547e860f15SJohn Edward Broadbent 255997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 256997093ebSGeorge Liu if (objPath.filename() != chassisId) 2571abe55efSEd Tanous { 258daf36e2eSEd Tanous continue; 259daf36e2eSEd Tanous } 26026f03899SShawn McCarney 2617e860f15SJohn Edward Broadbent auto health = 2627e860f15SJohn Edward Broadbent std::make_shared<HealthPopulate>(asyncResp); 263b49ac873SJames Feist 2641e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::vector<std::string>>( 2651e1e598dSJonathan Doman *crow::connections::systemBus, 2661e1e598dSJonathan Doman "xyz.openbmc_project.ObjectMapper", 2671e1e598dSJonathan Doman path + "/all_sensors", 2681e1e598dSJonathan Doman "xyz.openbmc_project.Association", "endpoints", 269168e20c1SEd Tanous [health](const boost::system::error_code ec2, 2701e1e598dSJonathan Doman const std::vector<std::string>& resp) { 27123a21a1cSEd Tanous if (ec2) 272b49ac873SJames Feist { 273b49ac873SJames Feist return; // no sensors = no failures 274b49ac873SJames Feist } 2751e1e598dSJonathan Doman health->inventory = resp; 2761e1e598dSJonathan Doman }); 277b49ac873SJames Feist 278b49ac873SJames Feist health->populate(); 279b49ac873SJames Feist 28026f6976fSEd Tanous if (connectionNames.empty()) 2811abe55efSEd Tanous { 2821c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 283e0d918bcSEd Tanous continue; 284daf36e2eSEd Tanous } 285e0d918bcSEd Tanous 28649c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.type"] = 2875ac5a2f4SGunnar Mills "#Chassis.v1_16_0.Chassis"; 28849c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.id"] = 28949c53ac9SJohnathan Mantey "/redfish/v1/Chassis/" + chassisId; 29049c53ac9SJohnathan Mantey asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 29149c53ac9SJohnathan Mantey asyncResp->res.jsonValue["ChassisType"] = "RackMount"; 2927e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] = 2937e860f15SJohn Edward Broadbent {{"target", "/redfish/v1/Chassis/" + chassisId + 294dd99e04bSP.K. Lee "/Actions/Chassis.Reset"}, 2951cb1a9e6SAppaRao Puli {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" + 2961cb1a9e6SAppaRao Puli chassisId + 2971cb1a9e6SAppaRao Puli "/ResetActionInfo"}}; 298adbe192aSJason M. Bills asyncResp->res.jsonValue["PCIeDevices"] = { 299adbe192aSJason M. Bills {"@odata.id", 300adbe192aSJason M. Bills "/redfish/v1/Systems/system/PCIeDevices"}}; 30149c53ac9SJohnathan Mantey 30249c53ac9SJohnathan Mantey const std::string& connectionName = 30349c53ac9SJohnathan Mantey connectionNames[0].first; 3041c8fba97SJames Feist 30523a21a1cSEd Tanous const std::vector<std::string>& interfaces2 = 3061c8fba97SJames Feist connectionNames[0].second; 3071c8fba97SJames Feist const std::array<const char*, 2> hasIndicatorLed = { 3081c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 3090fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 3101c8fba97SJames Feist 311476b9cc5STejas Patil const std::string assetTagInterface = 3120fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.AssetTag"; 313476b9cc5STejas Patil if (std::find(interfaces2.begin(), interfaces2.end(), 314476b9cc5STejas Patil assetTagInterface) != interfaces2.end()) 315476b9cc5STejas Patil { 3161e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 3171e1e598dSJonathan Doman *crow::connections::systemBus, connectionName, 3181e1e598dSJonathan Doman path, assetTagInterface, "AssetTag", 319476b9cc5STejas Patil [asyncResp, chassisId(std::string(chassisId))]( 320476b9cc5STejas Patil const boost::system::error_code ec, 3211e1e598dSJonathan Doman const std::string& property) { 322476b9cc5STejas Patil if (ec) 323476b9cc5STejas Patil { 324476b9cc5STejas Patil BMCWEB_LOG_DEBUG 3250fda0f12SGeorge Liu << "DBus response error for AssetTag"; 326476b9cc5STejas Patil messages::internalError(asyncResp->res); 327476b9cc5STejas Patil return; 328476b9cc5STejas Patil } 329476b9cc5STejas Patil asyncResp->res.jsonValue["AssetTag"] = 3301e1e598dSJonathan Doman property; 3311e1e598dSJonathan Doman }); 332476b9cc5STejas Patil } 333476b9cc5STejas Patil 3341c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 3351c8fba97SJames Feist { 3367e860f15SJohn Edward Broadbent if (std::find(interfaces2.begin(), 3377e860f15SJohn Edward Broadbent 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*/, 3497e860f15SJohn Edward Broadbent const std::vector< 350168e20c1SEd Tanous std::pair<std::string, 351168e20c1SEd Tanous dbus::utility::DbusVariantType>>& 3527e860f15SJohn Edward Broadbent propertiesList) { 353168e20c1SEd Tanous for (const std::pair< 354168e20c1SEd Tanous std::string, 355168e20c1SEd Tanous dbus::utility::DbusVariantType>& 3561214b7e7SGunnar Mills property : propertiesList) 3571abe55efSEd Tanous { 3587e860f15SJohn Edward Broadbent // Store DBus properties that are also 3597e860f15SJohn Edward Broadbent // Redfish properties with same name and a 3607e860f15SJohn Edward Broadbent // string value 36199cffd7fSShawn McCarney const std::string& propertyName = 36299cffd7fSShawn McCarney property.first; 36399cffd7fSShawn McCarney if ((propertyName == "PartNumber") || 36499cffd7fSShawn McCarney (propertyName == "SerialNumber") || 36599cffd7fSShawn McCarney (propertyName == "Manufacturer") || 366caa11f7aSAlpana Kumari (propertyName == "Model") || 367caa11f7aSAlpana Kumari (propertyName == "SparePartNumber")) 36899cffd7fSShawn McCarney { 369daf36e2eSEd Tanous const std::string* value = 37099cffd7fSShawn McCarney std::get_if<std::string>( 37199cffd7fSShawn McCarney &property.second); 372caa11f7aSAlpana Kumari if (value == nullptr) 3731abe55efSEd Tanous { 374caa11f7aSAlpana Kumari BMCWEB_LOG_ERROR 375caa11f7aSAlpana Kumari << "Null value returned for " 376caa11f7aSAlpana Kumari << propertyName; 377caa11f7aSAlpana Kumari messages::internalError( 378caa11f7aSAlpana Kumari asyncResp->res); 379caa11f7aSAlpana Kumari return; 380daf36e2eSEd Tanous } 381caa11f7aSAlpana Kumari // SparePartNumber is optional on D-Bus 382caa11f7aSAlpana Kumari // so skip if it is empty 383caa11f7aSAlpana Kumari if (propertyName == "SparePartNumber") 384caa11f7aSAlpana Kumari { 38526f6976fSEd Tanous if (value->empty()) 386caa11f7aSAlpana Kumari { 387caa11f7aSAlpana Kumari continue; 388caa11f7aSAlpana Kumari } 389caa11f7aSAlpana Kumari } 390caa11f7aSAlpana Kumari asyncResp->res.jsonValue[propertyName] = 391caa11f7aSAlpana Kumari *value; 392daf36e2eSEd Tanous } 39399cffd7fSShawn McCarney } 39462d5e2e4SEd Tanous asyncResp->res.jsonValue["Name"] = chassisId; 39562d5e2e4SEd Tanous asyncResp->res.jsonValue["Id"] = chassisId; 3960256b694Szhanghch05 #ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL 39762d5e2e4SEd Tanous asyncResp->res.jsonValue["Thermal"] = { 3981abe55efSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 3991abe55efSEd Tanous chassisId + "/Thermal"}}; 4002474adfaSEd Tanous // Power object 4012474adfaSEd Tanous asyncResp->res.jsonValue["Power"] = { 4022474adfaSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 4032474adfaSEd Tanous chassisId + "/Power"}}; 4040256b694Szhanghch05 #endif 40595a3ecadSAnthony Wilson // SensorCollection 40695a3ecadSAnthony Wilson asyncResp->res.jsonValue["Sensors"] = { 40795a3ecadSAnthony Wilson {"@odata.id", "/redfish/v1/Chassis/" + 40895a3ecadSAnthony Wilson chassisId + "/Sensors"}}; 409029573d4SEd Tanous asyncResp->res.jsonValue["Status"] = { 410029573d4SEd Tanous {"State", "Enabled"}, 411029573d4SEd Tanous }; 4122474adfaSEd Tanous 413029573d4SEd Tanous asyncResp->res 414029573d4SEd Tanous .jsonValue["Links"]["ComputerSystems"] = { 4157e860f15SJohn Edward Broadbent {{"@odata.id", 4167e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system"}}}; 4177e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Links"]["ManagedBy"] = 4187e860f15SJohn Edward Broadbent {{{"@odata.id", 4197e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc"}}}; 420beeca0aeSGunnar Mills getChassisState(asyncResp); 421daf36e2eSEd Tanous }, 4227e860f15SJohn Edward Broadbent connectionName, path, 4237e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "GetAll", 4241abe55efSEd Tanous "xyz.openbmc_project.Inventory.Decorator.Asset"); 4252c37b4b0SSharad Yadav 426308f70c7SWilly Tu for (const auto& interface : interfaces2) 4272c37b4b0SSharad Yadav { 428308f70c7SWilly Tu if (interface == "xyz.openbmc_project.Common.UUID") 4292c37b4b0SSharad Yadav { 430308f70c7SWilly Tu getChassisUUID(asyncResp, connectionName, path); 4312c37b4b0SSharad Yadav } 4320fda0f12SGeorge Liu else if ( 4330fda0f12SGeorge Liu interface == 4340fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 4352c37b4b0SSharad Yadav { 436308f70c7SWilly Tu getChassisLocationCode(asyncResp, 437308f70c7SWilly Tu connectionName, path); 4382c37b4b0SSharad Yadav } 4392c37b4b0SSharad Yadav } 4402c37b4b0SSharad Yadav 441daf36e2eSEd Tanous return; 442daf36e2eSEd Tanous } 443e0d918bcSEd Tanous 444daf36e2eSEd Tanous // Couldn't find an object with that name. return an error 445f12894f8SJason M. Bills messages::resourceNotFound( 4465ac5a2f4SGunnar Mills asyncResp->res, "#Chassis.v1_16_0.Chassis", chassisId); 447daf36e2eSEd Tanous }, 448daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", 449daf36e2eSEd Tanous "/xyz/openbmc_project/object_mapper", 450daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTree", 451271584abSEd Tanous "/xyz/openbmc_project/inventory", 0, interfaces); 452c181942fSQiang XU 453c181942fSQiang XU getPhysicalSecurityData(asyncResp); 4547e860f15SJohn Edward Broadbent }); 4551c8fba97SJames Feist 4567e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 457ed398213SEd Tanous .privileges(redfish::privileges::patchChassis) 4587e860f15SJohn Edward Broadbent .methods( 4597e860f15SJohn Edward Broadbent boost::beast::http::verb:: 4607e860f15SJohn Edward Broadbent patch)([](const crow::Request& req, 4617e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4627e860f15SJohn Edward Broadbent const std::string& param) { 4639f8bfa7cSGunnar Mills std::optional<bool> locationIndicatorActive; 4641c8fba97SJames Feist std::optional<std::string> indicatorLed; 4651c8fba97SJames Feist 4667e860f15SJohn Edward Broadbent if (param.empty()) 4671c8fba97SJames Feist { 4681c8fba97SJames Feist return; 4691c8fba97SJames Feist } 4701c8fba97SJames Feist 471*15ed6780SWilly Tu if (!json_util::readJsonPatch( 4727e860f15SJohn Edward Broadbent req, asyncResp->res, "LocationIndicatorActive", 4737e860f15SJohn Edward Broadbent locationIndicatorActive, "IndicatorLED", indicatorLed)) 4741c8fba97SJames Feist { 4751c8fba97SJames Feist return; 4761c8fba97SJames Feist } 4771c8fba97SJames Feist 4789f8bfa7cSGunnar Mills // TODO (Gunnar): Remove IndicatorLED after enough time has passed 4799f8bfa7cSGunnar Mills if (!locationIndicatorActive && !indicatorLed) 4801c8fba97SJames Feist { 4811c8fba97SJames Feist return; // delete this when we support more patch properties 4821c8fba97SJames Feist } 483d6aa0093SGunnar Mills if (indicatorLed) 484d6aa0093SGunnar Mills { 4857e860f15SJohn Edward Broadbent asyncResp->res.addHeader( 4867e860f15SJohn Edward Broadbent boost::beast::http::field::warning, 4870fda0f12SGeorge Liu "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\""); 488d6aa0093SGunnar Mills } 4891c8fba97SJames Feist 4901c8fba97SJames Feist const std::array<const char*, 2> interfaces = { 4911c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board", 4921c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Chassis"}; 4931c8fba97SJames Feist 4947e860f15SJohn Edward Broadbent const std::string& chassisId = param; 4951c8fba97SJames Feist 4961c8fba97SJames Feist crow::connections::systemBus->async_method_call( 4979f8bfa7cSGunnar Mills [asyncResp, chassisId, locationIndicatorActive, indicatorLed]( 4981c8fba97SJames Feist const boost::system::error_code ec, 4991c8fba97SJames Feist const crow::openbmc_mapper::GetSubTreeType& subtree) { 5001c8fba97SJames Feist if (ec) 5011c8fba97SJames Feist { 5021c8fba97SJames Feist messages::internalError(asyncResp->res); 5031c8fba97SJames Feist return; 5041c8fba97SJames Feist } 5051c8fba97SJames Feist 5061c8fba97SJames Feist // Iterate over all retrieved ObjectPaths. 5071c8fba97SJames Feist for (const std::pair< 5081c8fba97SJames Feist std::string, 5097e860f15SJohn Edward Broadbent std::vector<std::pair<std::string, 5107e860f15SJohn Edward Broadbent std::vector<std::string>>>>& 5111214b7e7SGunnar Mills object : subtree) 5121c8fba97SJames Feist { 5131c8fba97SJames Feist const std::string& path = object.first; 5141c8fba97SJames Feist const std::vector< 5151214b7e7SGunnar Mills std::pair<std::string, std::vector<std::string>>>& 5161214b7e7SGunnar Mills connectionNames = object.second; 5171c8fba97SJames Feist 518997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 519997093ebSGeorge Liu if (objPath.filename() != chassisId) 5201c8fba97SJames Feist { 5211c8fba97SJames Feist continue; 5221c8fba97SJames Feist } 5231c8fba97SJames Feist 52426f6976fSEd Tanous if (connectionNames.empty()) 5251c8fba97SJames Feist { 5261c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 5271c8fba97SJames Feist continue; 5281c8fba97SJames Feist } 5291c8fba97SJames Feist 53023a21a1cSEd Tanous const std::vector<std::string>& interfaces3 = 5311c8fba97SJames Feist connectionNames[0].second; 5321c8fba97SJames Feist 5331c8fba97SJames Feist const std::array<const char*, 2> hasIndicatorLed = { 5341c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 5350fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 5361c8fba97SJames Feist bool indicatorChassis = false; 5371c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 5381c8fba97SJames Feist { 5397e860f15SJohn Edward Broadbent if (std::find(interfaces3.begin(), 5407e860f15SJohn Edward Broadbent interfaces3.end(), 54123a21a1cSEd Tanous interface) != interfaces3.end()) 5421c8fba97SJames Feist { 5431c8fba97SJames Feist indicatorChassis = true; 5441c8fba97SJames Feist break; 5451c8fba97SJames Feist } 5461c8fba97SJames Feist } 5479f8bfa7cSGunnar Mills if (locationIndicatorActive) 5489f8bfa7cSGunnar Mills { 5499f8bfa7cSGunnar Mills if (indicatorChassis) 5509f8bfa7cSGunnar Mills { 5519f8bfa7cSGunnar Mills setLocationIndicatorActive( 5529f8bfa7cSGunnar Mills asyncResp, *locationIndicatorActive); 5539f8bfa7cSGunnar Mills } 5549f8bfa7cSGunnar Mills else 5559f8bfa7cSGunnar Mills { 5569f8bfa7cSGunnar Mills messages::propertyUnknown( 5579f8bfa7cSGunnar Mills asyncResp->res, "LocationIndicatorActive"); 5589f8bfa7cSGunnar Mills } 5599f8bfa7cSGunnar Mills } 5609f8bfa7cSGunnar Mills if (indicatorLed) 5619f8bfa7cSGunnar Mills { 5621c8fba97SJames Feist if (indicatorChassis) 5631c8fba97SJames Feist { 564f23b7296SEd Tanous setIndicatorLedState(asyncResp, *indicatorLed); 5651c8fba97SJames Feist } 5661c8fba97SJames Feist else 5671c8fba97SJames Feist { 5681c8fba97SJames Feist messages::propertyUnknown(asyncResp->res, 5691c8fba97SJames Feist "IndicatorLED"); 5701c8fba97SJames Feist } 5711c8fba97SJames Feist } 5721c8fba97SJames Feist return; 5731c8fba97SJames Feist } 5741c8fba97SJames Feist 5751c8fba97SJames Feist messages::resourceNotFound( 5769f8bfa7cSGunnar Mills asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId); 5771c8fba97SJames Feist }, 5781c8fba97SJames Feist "xyz.openbmc_project.ObjectMapper", 5791c8fba97SJames Feist "/xyz/openbmc_project/object_mapper", 5801c8fba97SJames Feist "xyz.openbmc_project.ObjectMapper", "GetSubTree", 5811c8fba97SJames Feist "/xyz/openbmc_project/inventory", 0, interfaces); 5827e860f15SJohn Edward Broadbent }); 5831c8fba97SJames Feist } 584dd99e04bSP.K. Lee 5858d1b46d7Szhanghch05 inline void 5868d1b46d7Szhanghch05 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 587dd99e04bSP.K. Lee { 588c3b3c92aSVijay Khemka const char* busName = "xyz.openbmc_project.ObjectMapper"; 589c3b3c92aSVijay Khemka const char* path = "/xyz/openbmc_project/object_mapper"; 590c3b3c92aSVijay Khemka const char* interface = "xyz.openbmc_project.ObjectMapper"; 591c3b3c92aSVijay Khemka const char* method = "GetSubTreePaths"; 592c3b3c92aSVijay Khemka 593c3b3c92aSVijay Khemka const std::array<const char*, 1> interfaces = { 594c3b3c92aSVijay Khemka "xyz.openbmc_project.State.Chassis"}; 595c3b3c92aSVijay Khemka 596c3b3c92aSVijay Khemka // Use mapper to get subtree paths. 597c3b3c92aSVijay Khemka crow::connections::systemBus->async_method_call( 598c3b3c92aSVijay Khemka [asyncResp](const boost::system::error_code ec, 599c3b3c92aSVijay Khemka const std::vector<std::string>& chassisList) { 600c3b3c92aSVijay Khemka if (ec) 601c3b3c92aSVijay Khemka { 602c3b3c92aSVijay Khemka BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec; 603c3b3c92aSVijay Khemka messages::internalError(asyncResp->res); 604c3b3c92aSVijay Khemka return; 605c3b3c92aSVijay Khemka } 606c3b3c92aSVijay Khemka 607dd99e04bSP.K. Lee const char* processName = "xyz.openbmc_project.State.Chassis"; 608dd99e04bSP.K. Lee const char* interfaceName = "xyz.openbmc_project.State.Chassis"; 609dd99e04bSP.K. Lee const char* destProperty = "RequestedPowerTransition"; 610dd99e04bSP.K. Lee const std::string propertyValue = 611dd99e04bSP.K. Lee "xyz.openbmc_project.State.Chassis.Transition.PowerCycle"; 612c3b3c92aSVijay Khemka std::string objectPath = 613c3b3c92aSVijay Khemka "/xyz/openbmc_project/state/chassis_system0"; 614c3b3c92aSVijay Khemka 615c3b3c92aSVijay Khemka /* Look for system reset chassis path */ 616c3b3c92aSVijay Khemka if ((std::find(chassisList.begin(), chassisList.end(), 617c3b3c92aSVijay Khemka objectPath)) == chassisList.end()) 618c3b3c92aSVijay Khemka { 619c3b3c92aSVijay Khemka /* We prefer to reset the full chassis_system, but if it doesn't 620c3b3c92aSVijay Khemka * exist on some platforms, fall back to a host-only power reset 621c3b3c92aSVijay Khemka */ 622c3b3c92aSVijay Khemka objectPath = "/xyz/openbmc_project/state/chassis0"; 623c3b3c92aSVijay Khemka } 624dd99e04bSP.K. Lee 625dd99e04bSP.K. Lee crow::connections::systemBus->async_method_call( 626dd99e04bSP.K. Lee [asyncResp](const boost::system::error_code ec) { 627dd99e04bSP.K. Lee // Use "Set" method to set the property value. 628dd99e04bSP.K. Lee if (ec) 629dd99e04bSP.K. Lee { 630c3b3c92aSVijay Khemka BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: " 631c3b3c92aSVijay Khemka << ec; 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 }, 638c3b3c92aSVijay Khemka processName, objectPath, "org.freedesktop.DBus.Properties", 639c3b3c92aSVijay Khemka "Set", interfaceName, destProperty, 640168e20c1SEd Tanous dbus::utility::DbusVariantType{propertyValue}); 641c3b3c92aSVijay Khemka }, 642c3b3c92aSVijay Khemka busName, path, interface, method, "/", 0, interfaces); 643dd99e04bSP.K. Lee } 644dd99e04bSP.K. Lee 645dd99e04bSP.K. Lee /** 646dd99e04bSP.K. Lee * ChassisResetAction class supports the POST method for the Reset 647dd99e04bSP.K. Lee * action. 648dd99e04bSP.K. Lee * Function handles POST method request. 649dd99e04bSP.K. Lee * Analyzes POST body before sending Reset request data to D-Bus. 650dd99e04bSP.K. Lee */ 6517e860f15SJohn Edward Broadbent 6527e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetAction(App& app) 653dd99e04bSP.K. Lee { 6547e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/") 655ed398213SEd Tanous .privileges(redfish::privileges::postChassis) 6567e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 6577e860f15SJohn Edward Broadbent [](const crow::Request& req, 6587e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6597e860f15SJohn Edward Broadbent const std::string&) { 660dd99e04bSP.K. Lee BMCWEB_LOG_DEBUG << "Post Chassis Reset."; 661dd99e04bSP.K. Lee 662dd99e04bSP.K. Lee std::string resetType; 663dd99e04bSP.K. Lee 664*15ed6780SWilly Tu if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", 6657e860f15SJohn Edward Broadbent resetType)) 666dd99e04bSP.K. Lee { 667dd99e04bSP.K. Lee return; 668dd99e04bSP.K. Lee } 669dd99e04bSP.K. Lee 670dd99e04bSP.K. Lee if (resetType != "PowerCycle") 671dd99e04bSP.K. Lee { 672dd99e04bSP.K. Lee BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: " 673dd99e04bSP.K. Lee << resetType; 6747e860f15SJohn Edward Broadbent messages::actionParameterNotSupported( 6757e860f15SJohn Edward Broadbent asyncResp->res, resetType, "ResetType"); 676dd99e04bSP.K. Lee 677dd99e04bSP.K. Lee return; 678dd99e04bSP.K. Lee } 679dd99e04bSP.K. Lee doChassisPowerCycle(asyncResp); 6807e860f15SJohn Edward Broadbent }); 681dd99e04bSP.K. Lee } 6821cb1a9e6SAppaRao Puli 6831cb1a9e6SAppaRao Puli /** 6841cb1a9e6SAppaRao Puli * ChassisResetActionInfo derived class for delivering Chassis 6851cb1a9e6SAppaRao Puli * ResetType AllowableValues using ResetInfo schema. 6861cb1a9e6SAppaRao Puli */ 6877e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetActionInfo(App& app) 6881cb1a9e6SAppaRao Puli { 6897e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/") 690ed398213SEd Tanous .privileges(redfish::privileges::getActionInfo) 6917e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 6927e860f15SJohn Edward Broadbent [](const crow::Request&, 6937e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6947e860f15SJohn Edward Broadbent const std::string& chassisId) 6951cb1a9e6SAppaRao Puli 6961cb1a9e6SAppaRao Puli { 6978d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 6988d1b46d7Szhanghch05 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"}, 6998d1b46d7Szhanghch05 {"@odata.id", 7008d1b46d7Szhanghch05 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"}, 7011cb1a9e6SAppaRao Puli {"Name", "Reset Action Info"}, 7021cb1a9e6SAppaRao Puli {"Id", "ResetActionInfo"}, 7031cb1a9e6SAppaRao Puli {"Parameters", 7041cb1a9e6SAppaRao Puli {{{"Name", "ResetType"}, 7051cb1a9e6SAppaRao Puli {"Required", true}, 7061cb1a9e6SAppaRao Puli {"DataType", "String"}, 7071cb1a9e6SAppaRao Puli {"AllowableValues", {"PowerCycle"}}}}}}; 7087e860f15SJohn Edward Broadbent }); 7091cb1a9e6SAppaRao Puli } 7101cb1a9e6SAppaRao Puli 711e37f8451SRapkiewicz, Pawel } // namespace redfish 712