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> 23ed398213SEd Tanous #include <registries/privilege_registry.hpp> 2402f6ff19SGunnar Mills #include <utils/collection.hpp> 251214b7e7SGunnar Mills 26abf2add6SEd Tanous #include <variant> 27e37f8451SRapkiewicz, Pawel 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 { 40beeca0aeSGunnar Mills crow::connections::systemBus->async_method_call( 41beeca0aeSGunnar Mills [aResp{std::move(aResp)}]( 42beeca0aeSGunnar Mills const boost::system::error_code ec, 43beeca0aeSGunnar Mills const std::variant<std::string>& chassisState) { 44beeca0aeSGunnar Mills if (ec) 45beeca0aeSGunnar Mills { 46beeca0aeSGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 47beeca0aeSGunnar Mills messages::internalError(aResp->res); 48beeca0aeSGunnar Mills return; 49beeca0aeSGunnar Mills } 50beeca0aeSGunnar Mills 51beeca0aeSGunnar Mills const std::string* s = std::get_if<std::string>(&chassisState); 52beeca0aeSGunnar Mills BMCWEB_LOG_DEBUG << "Chassis state: " << *s; 53beeca0aeSGunnar Mills if (s != nullptr) 54beeca0aeSGunnar Mills { 55beeca0aeSGunnar Mills // Verify Chassis State 56beeca0aeSGunnar Mills if (*s == "xyz.openbmc_project.State.Chassis.PowerState.On") 57beeca0aeSGunnar Mills { 58beeca0aeSGunnar Mills aResp->res.jsonValue["PowerState"] = "On"; 59beeca0aeSGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Enabled"; 60beeca0aeSGunnar Mills } 61beeca0aeSGunnar Mills else if (*s == 62beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis.PowerState.Off") 63beeca0aeSGunnar Mills { 64beeca0aeSGunnar Mills aResp->res.jsonValue["PowerState"] = "Off"; 65beeca0aeSGunnar Mills aResp->res.jsonValue["Status"]["State"] = "StandbyOffline"; 66beeca0aeSGunnar Mills } 67beeca0aeSGunnar Mills } 68beeca0aeSGunnar Mills }, 69beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis", 70beeca0aeSGunnar Mills "/xyz/openbmc_project/state/chassis0", 71beeca0aeSGunnar Mills "org.freedesktop.DBus.Properties", "Get", 72beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis", "CurrentPowerState"); 73beeca0aeSGunnar Mills } 74beeca0aeSGunnar Mills 75beeca0aeSGunnar Mills /** 76e37f8451SRapkiewicz, Pawel * DBus types primitives for several generic DBus interfaces 77e37f8451SRapkiewicz, Pawel * TODO(Pawel) consider move this to separate file into boost::dbus 78e37f8451SRapkiewicz, Pawel */ 7955c7b7a2SEd Tanous // Note, this is not a very useful Variant, but because it isn't used to get 80aa2e59c1SEd Tanous // values, it should be as simple as possible 81aa2e59c1SEd Tanous // TODO(ed) invent a nullvariant type 825fd7ba65SCheng C Yang using VariantType = std::variant<bool, std::string, uint64_t, uint32_t>; 83aa2e59c1SEd Tanous using ManagedObjectsType = std::vector<std::pair< 84aa2e59c1SEd Tanous sdbusplus::message::object_path, 85aa2e59c1SEd Tanous std::vector<std::pair<std::string, 86aa2e59c1SEd Tanous std::vector<std::pair<std::string, VariantType>>>>>>; 87e37f8451SRapkiewicz, Pawel 88aa2e59c1SEd Tanous using PropertiesType = boost::container::flat_map<std::string, VariantType>; 89e37f8451SRapkiewicz, Pawel 908d1b46d7Szhanghch05 inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp, 91c181942fSQiang XU const std::string& service, 92c181942fSQiang XU const std::string& objPath) 93c181942fSQiang XU { 94c181942fSQiang XU BMCWEB_LOG_DEBUG << "Get intrusion status by service \n"; 95c181942fSQiang XU 96c181942fSQiang XU crow::connections::systemBus->async_method_call( 97c181942fSQiang XU [aResp{std::move(aResp)}](const boost::system::error_code ec, 98c181942fSQiang XU const std::variant<std::string>& value) { 99c181942fSQiang XU if (ec) 100c181942fSQiang XU { 1014e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 102c181942fSQiang XU // mandatory property 103c181942fSQiang XU BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n"; 104c181942fSQiang XU return; 105c181942fSQiang XU } 106c181942fSQiang XU 107c181942fSQiang XU const std::string* status = std::get_if<std::string>(&value); 108c181942fSQiang XU 109c181942fSQiang XU if (status == nullptr) 110c181942fSQiang XU { 111c181942fSQiang XU BMCWEB_LOG_ERROR << "intrusion status read error \n"; 112c181942fSQiang XU return; 113c181942fSQiang XU } 114c181942fSQiang XU 115c181942fSQiang XU aResp->res.jsonValue["PhysicalSecurity"] = { 116c181942fSQiang XU {"IntrusionSensorNumber", 1}, {"IntrusionSensor", *status}}; 117c181942fSQiang XU }, 118c181942fSQiang XU service, objPath, "org.freedesktop.DBus.Properties", "Get", 119c181942fSQiang XU "xyz.openbmc_project.Chassis.Intrusion", "Status"); 120c181942fSQiang XU } 121c181942fSQiang XU 122c181942fSQiang XU /** 123c181942fSQiang XU * Retrieves physical security properties over dbus 124c181942fSQiang XU */ 1258d1b46d7Szhanghch05 inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp) 126c181942fSQiang XU { 127c181942fSQiang XU crow::connections::systemBus->async_method_call( 128c181942fSQiang XU [aResp{std::move(aResp)}]( 129c181942fSQiang XU const boost::system::error_code ec, 130c181942fSQiang XU const std::vector<std::pair< 131c181942fSQiang XU std::string, 1321214b7e7SGunnar Mills std::vector<std::pair<std::string, std::vector<std::string>>>>>& 1331214b7e7SGunnar Mills subtree) { 134c181942fSQiang XU if (ec) 135c181942fSQiang XU { 1364e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 137c181942fSQiang XU // mandatory property 138c181942fSQiang XU BMCWEB_LOG_ERROR << "DBUS error: no matched iface " << ec 139c181942fSQiang XU << "\n"; 140c181942fSQiang XU return; 141c181942fSQiang XU } 142c181942fSQiang XU // Iterate over all retrieved ObjectPaths. 143c181942fSQiang XU for (const auto& object : subtree) 144c181942fSQiang XU { 145c181942fSQiang XU for (const auto& service : object.second) 146c181942fSQiang XU { 147c181942fSQiang XU getIntrusionByService(aResp, service.first, object.first); 148c181942fSQiang XU return; 149c181942fSQiang XU } 150c181942fSQiang XU } 151c181942fSQiang XU }, 152c181942fSQiang XU "xyz.openbmc_project.ObjectMapper", 153c181942fSQiang XU "/xyz/openbmc_project/object_mapper", 154c181942fSQiang XU "xyz.openbmc_project.ObjectMapper", "GetSubTree", 155271584abSEd Tanous "/xyz/openbmc_project/Intrusion", 1, 156c181942fSQiang XU std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"}); 157c181942fSQiang XU } 158c181942fSQiang XU 159e37f8451SRapkiewicz, Pawel /** 160e37f8451SRapkiewicz, Pawel * ChassisCollection derived class for delivering Chassis Collection Schema 161e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 162e37f8451SRapkiewicz, Pawel */ 1637e860f15SJohn Edward Broadbent inline void requestRoutesChassisCollection(App& app) 1641abe55efSEd Tanous { 1657e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/") 166ed398213SEd Tanous .privileges(redfish::privileges::getChassisCollection) 1677e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 1687e860f15SJohn Edward Broadbent [](const crow::Request&, 1697e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1708d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1718d1b46d7Szhanghch05 "#ChassisCollection.ChassisCollection"; 1728d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 1738d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 174e37f8451SRapkiewicz, Pawel 17502f6ff19SGunnar Mills collection_util::getCollectionMembers( 17602f6ff19SGunnar Mills asyncResp, "/redfish/v1/Chassis", 17702f6ff19SGunnar Mills {"xyz.openbmc_project.Inventory.Item.Board", 17802f6ff19SGunnar Mills "xyz.openbmc_project.Inventory.Item.Chassis"}); 1797e860f15SJohn Edward Broadbent }); 18062d5e2e4SEd Tanous } 181e37f8451SRapkiewicz, Pawel 182e37f8451SRapkiewicz, Pawel /** 183e37f8451SRapkiewicz, Pawel * Chassis override class for delivering Chassis Schema 184e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 185e37f8451SRapkiewicz, Pawel */ 1867e860f15SJohn Edward Broadbent inline void requestRoutesChassis(App& app) 1871abe55efSEd Tanous { 1887e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 189ed398213SEd Tanous .privileges(redfish::privileges::getChassis) 1907e860f15SJohn Edward Broadbent .methods( 1917e860f15SJohn Edward Broadbent boost::beast::http::verb::get)([](const crow::Request&, 1927e860f15SJohn Edward Broadbent const std::shared_ptr< 1937e860f15SJohn Edward Broadbent bmcweb::AsyncResp>& asyncResp, 1947e860f15SJohn Edward Broadbent const std::string& chassisId) { 195adc4f0dbSShawn McCarney const std::array<const char*, 2> interfaces = { 196734bfe90SGunnar Mills "xyz.openbmc_project.Inventory.Item.Board", 197adc4f0dbSShawn McCarney "xyz.openbmc_project.Inventory.Item.Chassis"}; 198734bfe90SGunnar Mills 19955c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 20062d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 20162d5e2e4SEd Tanous const boost::system::error_code ec, 2021c8fba97SJames Feist const crow::openbmc_mapper::GetSubTreeType& subtree) { 20362d5e2e4SEd Tanous if (ec) 2041abe55efSEd Tanous { 205f12894f8SJason M. Bills messages::internalError(asyncResp->res); 206daf36e2eSEd Tanous return; 207daf36e2eSEd Tanous } 208daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 2091abe55efSEd Tanous for (const std::pair< 2101abe55efSEd Tanous std::string, 2117e860f15SJohn Edward Broadbent std::vector<std::pair<std::string, 2127e860f15SJohn Edward Broadbent std::vector<std::string>>>>& 2131214b7e7SGunnar Mills object : subtree) 2141abe55efSEd Tanous { 215daf36e2eSEd Tanous const std::string& path = object.first; 2161abe55efSEd Tanous const std::vector< 2171214b7e7SGunnar Mills std::pair<std::string, std::vector<std::string>>>& 2181214b7e7SGunnar Mills connectionNames = object.second; 2197e860f15SJohn Edward Broadbent 2207e860f15SJohn Edward Broadbent if (!boost::ends_with(path, chassisId)) 2211abe55efSEd Tanous { 222daf36e2eSEd Tanous continue; 223daf36e2eSEd Tanous } 22426f03899SShawn McCarney 2257e860f15SJohn Edward Broadbent auto health = 2267e860f15SJohn Edward Broadbent std::make_shared<HealthPopulate>(asyncResp); 227b49ac873SJames Feist 228b49ac873SJames Feist crow::connections::systemBus->async_method_call( 2297e860f15SJohn Edward Broadbent [health]( 2307e860f15SJohn Edward Broadbent const boost::system::error_code ec2, 231b49ac873SJames Feist std::variant<std::vector<std::string>>& resp) { 23223a21a1cSEd Tanous if (ec2) 233b49ac873SJames Feist { 234b49ac873SJames Feist return; // no sensors = no failures 235b49ac873SJames Feist } 236b49ac873SJames Feist std::vector<std::string>* data = 2377e860f15SJohn Edward Broadbent std::get_if<std::vector<std::string>>( 2387e860f15SJohn Edward Broadbent &resp); 239b49ac873SJames Feist if (data == nullptr) 240b49ac873SJames Feist { 241b49ac873SJames Feist return; 242b49ac873SJames Feist } 243b49ac873SJames Feist health->inventory = std::move(*data); 244b49ac873SJames Feist }, 245b49ac873SJames Feist "xyz.openbmc_project.ObjectMapper", 246b49ac873SJames Feist path + "/all_sensors", 247b49ac873SJames Feist "org.freedesktop.DBus.Properties", "Get", 248b49ac873SJames Feist "xyz.openbmc_project.Association", "endpoints"); 249b49ac873SJames Feist 250b49ac873SJames Feist health->populate(); 251b49ac873SJames Feist 2521abe55efSEd Tanous if (connectionNames.size() < 1) 2531abe55efSEd Tanous { 2541c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 255e0d918bcSEd Tanous continue; 256daf36e2eSEd Tanous } 257e0d918bcSEd Tanous 25849c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.type"] = 2599f8bfa7cSGunnar Mills "#Chassis.v1_14_0.Chassis"; 26049c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.id"] = 26149c53ac9SJohnathan Mantey "/redfish/v1/Chassis/" + chassisId; 26249c53ac9SJohnathan Mantey asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 26349c53ac9SJohnathan Mantey asyncResp->res.jsonValue["ChassisType"] = "RackMount"; 2647e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] = 2657e860f15SJohn Edward Broadbent {{"target", "/redfish/v1/Chassis/" + chassisId + 266dd99e04bSP.K. Lee "/Actions/Chassis.Reset"}, 2671cb1a9e6SAppaRao Puli {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" + 2681cb1a9e6SAppaRao Puli chassisId + 2691cb1a9e6SAppaRao Puli "/ResetActionInfo"}}; 270adbe192aSJason M. Bills asyncResp->res.jsonValue["PCIeDevices"] = { 271adbe192aSJason M. Bills {"@odata.id", 272adbe192aSJason M. Bills "/redfish/v1/Systems/system/PCIeDevices"}}; 27349c53ac9SJohnathan Mantey 27449c53ac9SJohnathan Mantey const std::string& connectionName = 27549c53ac9SJohnathan Mantey connectionNames[0].first; 2761c8fba97SJames Feist 27723a21a1cSEd Tanous const std::vector<std::string>& interfaces2 = 2781c8fba97SJames Feist connectionNames[0].second; 2791c8fba97SJames Feist const std::array<const char*, 2> hasIndicatorLed = { 2801c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 2817e860f15SJohn Edward Broadbent "xyz.openbmc_project.Inventory.Item.Board." 2827e860f15SJohn Edward Broadbent "Motherboard"}; 2831c8fba97SJames Feist 284*476b9cc5STejas Patil const std::string assetTagInterface = 285*476b9cc5STejas Patil "xyz.openbmc_project.Inventory.Decorator." 286*476b9cc5STejas Patil "AssetTag"; 287*476b9cc5STejas Patil if (std::find(interfaces2.begin(), interfaces2.end(), 288*476b9cc5STejas Patil assetTagInterface) != interfaces2.end()) 289*476b9cc5STejas Patil { 290*476b9cc5STejas Patil crow::connections::systemBus->async_method_call( 291*476b9cc5STejas Patil [asyncResp, chassisId(std::string(chassisId))]( 292*476b9cc5STejas Patil const boost::system::error_code ec, 293*476b9cc5STejas Patil const std::variant<std::string>& property) { 294*476b9cc5STejas Patil if (ec) 295*476b9cc5STejas Patil { 296*476b9cc5STejas Patil BMCWEB_LOG_DEBUG 297*476b9cc5STejas Patil << "DBus response error for " 298*476b9cc5STejas Patil "AssetTag"; 299*476b9cc5STejas Patil messages::internalError(asyncResp->res); 300*476b9cc5STejas Patil return; 301*476b9cc5STejas Patil } 302*476b9cc5STejas Patil 303*476b9cc5STejas Patil const std::string* assetTag = 304*476b9cc5STejas Patil std::get_if<std::string>(&property); 305*476b9cc5STejas Patil if (assetTag == nullptr) 306*476b9cc5STejas Patil { 307*476b9cc5STejas Patil BMCWEB_LOG_DEBUG 308*476b9cc5STejas Patil << "Null value returned " 309*476b9cc5STejas Patil "for Chassis AssetTag"; 310*476b9cc5STejas Patil messages::internalError(asyncResp->res); 311*476b9cc5STejas Patil return; 312*476b9cc5STejas Patil } 313*476b9cc5STejas Patil asyncResp->res.jsonValue["AssetTag"] = 314*476b9cc5STejas Patil *assetTag; 315*476b9cc5STejas Patil }, 316*476b9cc5STejas Patil connectionName, path, 317*476b9cc5STejas Patil "org.freedesktop.DBus.Properties", "Get", 318*476b9cc5STejas Patil assetTagInterface, "AssetTag"); 319*476b9cc5STejas Patil } 320*476b9cc5STejas Patil 3211c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 3221c8fba97SJames Feist { 3237e860f15SJohn Edward Broadbent if (std::find(interfaces2.begin(), 3247e860f15SJohn Edward Broadbent interfaces2.end(), 32523a21a1cSEd Tanous interface) != interfaces2.end()) 3261c8fba97SJames Feist { 3271c8fba97SJames Feist getIndicatorLedState(asyncResp); 3289f8bfa7cSGunnar Mills getLocationIndicatorActive(asyncResp); 3291c8fba97SJames Feist break; 3301c8fba97SJames Feist } 3311c8fba97SJames Feist } 3321c8fba97SJames Feist 33388ad7f03SSunnySrivastava1984 const std::string locationInterface = 3347e860f15SJohn Edward Broadbent "xyz.openbmc_project.Inventory.Decorator." 3357e860f15SJohn Edward Broadbent "LocationCode"; 33688ad7f03SSunnySrivastava1984 if (std::find(interfaces2.begin(), interfaces2.end(), 33788ad7f03SSunnySrivastava1984 locationInterface) != interfaces2.end()) 33888ad7f03SSunnySrivastava1984 { 33988ad7f03SSunnySrivastava1984 crow::connections::systemBus->async_method_call( 34088ad7f03SSunnySrivastava1984 [asyncResp, chassisId(std::string(chassisId))]( 34188ad7f03SSunnySrivastava1984 const boost::system::error_code ec, 34288ad7f03SSunnySrivastava1984 const std::variant<std::string>& property) { 34388ad7f03SSunnySrivastava1984 if (ec) 34488ad7f03SSunnySrivastava1984 { 34588ad7f03SSunnySrivastava1984 BMCWEB_LOG_DEBUG 3467e860f15SJohn Edward Broadbent << "DBUS response error for " 3477e860f15SJohn Edward Broadbent "Location"; 34888ad7f03SSunnySrivastava1984 messages::internalError(asyncResp->res); 34988ad7f03SSunnySrivastava1984 return; 35088ad7f03SSunnySrivastava1984 } 35188ad7f03SSunnySrivastava1984 35288ad7f03SSunnySrivastava1984 const std::string* value = 35388ad7f03SSunnySrivastava1984 std::get_if<std::string>(&property); 35488ad7f03SSunnySrivastava1984 if (value == nullptr) 35588ad7f03SSunnySrivastava1984 { 3567e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG 3577e860f15SJohn Edward Broadbent << "Null value returned " 35888ad7f03SSunnySrivastava1984 "for locaton code"; 35988ad7f03SSunnySrivastava1984 messages::internalError(asyncResp->res); 36088ad7f03SSunnySrivastava1984 return; 36188ad7f03SSunnySrivastava1984 } 36288ad7f03SSunnySrivastava1984 asyncResp->res 36388ad7f03SSunnySrivastava1984 .jsonValue["Location"]["PartLocation"] 36488ad7f03SSunnySrivastava1984 ["ServiceLabel"] = *value; 36588ad7f03SSunnySrivastava1984 }, 36688ad7f03SSunnySrivastava1984 connectionName, path, 36788ad7f03SSunnySrivastava1984 "org.freedesktop.DBus.Properties", "Get", 36888ad7f03SSunnySrivastava1984 locationInterface, "LocationCode"); 36988ad7f03SSunnySrivastava1984 } 37088ad7f03SSunnySrivastava1984 37155c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 37262d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 37390728b54SEd Tanous const boost::system::error_code /*ec2*/, 3747e860f15SJohn Edward Broadbent const std::vector< 3757e860f15SJohn Edward Broadbent std::pair<std::string, VariantType>>& 3767e860f15SJohn Edward Broadbent propertiesList) { 3771214b7e7SGunnar Mills for (const std::pair<std::string, VariantType>& 3781214b7e7SGunnar Mills property : propertiesList) 3791abe55efSEd Tanous { 3807e860f15SJohn Edward Broadbent // Store DBus properties that are also 3817e860f15SJohn Edward Broadbent // Redfish properties with same name and a 3827e860f15SJohn Edward Broadbent // string value 38399cffd7fSShawn McCarney const std::string& propertyName = 38499cffd7fSShawn McCarney property.first; 38599cffd7fSShawn McCarney if ((propertyName == "PartNumber") || 38699cffd7fSShawn McCarney (propertyName == "SerialNumber") || 38799cffd7fSShawn McCarney (propertyName == "Manufacturer") || 38899cffd7fSShawn McCarney (propertyName == "Model")) 38999cffd7fSShawn McCarney { 390daf36e2eSEd Tanous const std::string* value = 39199cffd7fSShawn McCarney std::get_if<std::string>( 39299cffd7fSShawn McCarney &property.second); 3931abe55efSEd Tanous if (value != nullptr) 3941abe55efSEd Tanous { 3957e860f15SJohn Edward Broadbent asyncResp->res 3967e860f15SJohn Edward Broadbent .jsonValue[propertyName] = 39762d5e2e4SEd Tanous *value; 398daf36e2eSEd Tanous } 399daf36e2eSEd Tanous } 40099cffd7fSShawn McCarney } 40162d5e2e4SEd Tanous asyncResp->res.jsonValue["Name"] = chassisId; 40262d5e2e4SEd Tanous asyncResp->res.jsonValue["Id"] = chassisId; 4030256b694Szhanghch05 #ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL 40462d5e2e4SEd Tanous asyncResp->res.jsonValue["Thermal"] = { 4051abe55efSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 4061abe55efSEd Tanous chassisId + "/Thermal"}}; 4072474adfaSEd Tanous // Power object 4082474adfaSEd Tanous asyncResp->res.jsonValue["Power"] = { 4092474adfaSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 4102474adfaSEd Tanous chassisId + "/Power"}}; 4110256b694Szhanghch05 #endif 41295a3ecadSAnthony Wilson // SensorCollection 41395a3ecadSAnthony Wilson asyncResp->res.jsonValue["Sensors"] = { 41495a3ecadSAnthony Wilson {"@odata.id", "/redfish/v1/Chassis/" + 41595a3ecadSAnthony Wilson chassisId + "/Sensors"}}; 416029573d4SEd Tanous asyncResp->res.jsonValue["Status"] = { 417029573d4SEd Tanous {"State", "Enabled"}, 418029573d4SEd Tanous }; 4192474adfaSEd Tanous 420029573d4SEd Tanous asyncResp->res 421029573d4SEd Tanous .jsonValue["Links"]["ComputerSystems"] = { 4227e860f15SJohn Edward Broadbent {{"@odata.id", 4237e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system"}}}; 4247e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Links"]["ManagedBy"] = 4257e860f15SJohn Edward Broadbent {{{"@odata.id", 4267e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc"}}}; 427beeca0aeSGunnar Mills getChassisState(asyncResp); 428daf36e2eSEd Tanous }, 4297e860f15SJohn Edward Broadbent connectionName, path, 4307e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "GetAll", 4311abe55efSEd Tanous "xyz.openbmc_project.Inventory.Decorator.Asset"); 4322c37b4b0SSharad Yadav 4332c37b4b0SSharad Yadav // Chassis UUID 4342c37b4b0SSharad Yadav const std::string uuidInterface = 4352c37b4b0SSharad Yadav "xyz.openbmc_project.Common.UUID"; 4362c37b4b0SSharad Yadav if (std::find(interfaces2.begin(), interfaces2.end(), 4372c37b4b0SSharad Yadav uuidInterface) != interfaces2.end()) 4382c37b4b0SSharad Yadav { 4392c37b4b0SSharad Yadav crow::connections::systemBus->async_method_call( 4402c37b4b0SSharad Yadav [asyncResp](const boost::system::error_code ec, 4412c37b4b0SSharad Yadav const std::variant<std::string>& 4422c37b4b0SSharad Yadav chassisUUID) { 4432c37b4b0SSharad Yadav if (ec) 4442c37b4b0SSharad Yadav { 4452c37b4b0SSharad Yadav BMCWEB_LOG_DEBUG 4462c37b4b0SSharad Yadav << "DBUS response error for " 4472c37b4b0SSharad Yadav "UUID"; 4482c37b4b0SSharad Yadav messages::internalError(asyncResp->res); 4492c37b4b0SSharad Yadav return; 4502c37b4b0SSharad Yadav } 4512c37b4b0SSharad Yadav const std::string* value = 4522c37b4b0SSharad Yadav std::get_if<std::string>(&chassisUUID); 4532c37b4b0SSharad Yadav if (value == nullptr) 4542c37b4b0SSharad Yadav { 4552c37b4b0SSharad Yadav BMCWEB_LOG_DEBUG 4562c37b4b0SSharad Yadav << "Null value returned " 4572c37b4b0SSharad Yadav "for UUID"; 4582c37b4b0SSharad Yadav messages::internalError(asyncResp->res); 4592c37b4b0SSharad Yadav return; 4602c37b4b0SSharad Yadav } 4612c37b4b0SSharad Yadav asyncResp->res.jsonValue["UUID"] = *value; 4622c37b4b0SSharad Yadav }, 4632c37b4b0SSharad Yadav connectionName, path, 4642c37b4b0SSharad Yadav "org.freedesktop.DBus.Properties", "Get", 4652c37b4b0SSharad Yadav uuidInterface, "UUID"); 4662c37b4b0SSharad Yadav } 4672c37b4b0SSharad Yadav 468daf36e2eSEd Tanous return; 469daf36e2eSEd Tanous } 470e0d918bcSEd Tanous 471daf36e2eSEd Tanous // Couldn't find an object with that name. return an error 472f12894f8SJason M. Bills messages::resourceNotFound( 4739f8bfa7cSGunnar Mills asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId); 474daf36e2eSEd Tanous }, 475daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", 476daf36e2eSEd Tanous "/xyz/openbmc_project/object_mapper", 477daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTree", 478271584abSEd Tanous "/xyz/openbmc_project/inventory", 0, interfaces); 479c181942fSQiang XU 480c181942fSQiang XU getPhysicalSecurityData(asyncResp); 4817e860f15SJohn Edward Broadbent }); 4821c8fba97SJames Feist 4837e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 484ed398213SEd Tanous .privileges(redfish::privileges::patchChassis) 4857e860f15SJohn Edward Broadbent .methods( 4867e860f15SJohn Edward Broadbent boost::beast::http::verb:: 4877e860f15SJohn Edward Broadbent patch)([](const crow::Request& req, 4887e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4897e860f15SJohn Edward Broadbent const std::string& param) { 4909f8bfa7cSGunnar Mills std::optional<bool> locationIndicatorActive; 4911c8fba97SJames Feist std::optional<std::string> indicatorLed; 4921c8fba97SJames Feist 4937e860f15SJohn Edward Broadbent if (param.empty()) 4941c8fba97SJames Feist { 4951c8fba97SJames Feist return; 4961c8fba97SJames Feist } 4971c8fba97SJames Feist 4987e860f15SJohn Edward Broadbent if (!json_util::readJson( 4997e860f15SJohn Edward Broadbent req, asyncResp->res, "LocationIndicatorActive", 5007e860f15SJohn Edward Broadbent locationIndicatorActive, "IndicatorLED", indicatorLed)) 5011c8fba97SJames Feist { 5021c8fba97SJames Feist return; 5031c8fba97SJames Feist } 5041c8fba97SJames Feist 5059f8bfa7cSGunnar Mills // TODO (Gunnar): Remove IndicatorLED after enough time has passed 5069f8bfa7cSGunnar Mills if (!locationIndicatorActive && !indicatorLed) 5071c8fba97SJames Feist { 5081c8fba97SJames Feist return; // delete this when we support more patch properties 5091c8fba97SJames Feist } 510d6aa0093SGunnar Mills if (indicatorLed) 511d6aa0093SGunnar Mills { 5127e860f15SJohn Edward Broadbent asyncResp->res.addHeader( 5137e860f15SJohn Edward Broadbent boost::beast::http::field::warning, 514d6aa0093SGunnar Mills "299 - \"IndicatorLED is deprecated. Use " 515d6aa0093SGunnar Mills "LocationIndicatorActive instead.\""); 516d6aa0093SGunnar Mills } 5171c8fba97SJames Feist 5181c8fba97SJames Feist const std::array<const char*, 2> interfaces = { 5191c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board", 5201c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Chassis"}; 5211c8fba97SJames Feist 5227e860f15SJohn Edward Broadbent const std::string& chassisId = param; 5231c8fba97SJames Feist 5241c8fba97SJames Feist crow::connections::systemBus->async_method_call( 5259f8bfa7cSGunnar Mills [asyncResp, chassisId, locationIndicatorActive, indicatorLed]( 5261c8fba97SJames Feist const boost::system::error_code ec, 5271c8fba97SJames Feist const crow::openbmc_mapper::GetSubTreeType& subtree) { 5281c8fba97SJames Feist if (ec) 5291c8fba97SJames Feist { 5301c8fba97SJames Feist messages::internalError(asyncResp->res); 5311c8fba97SJames Feist return; 5321c8fba97SJames Feist } 5331c8fba97SJames Feist 5341c8fba97SJames Feist // Iterate over all retrieved ObjectPaths. 5351c8fba97SJames Feist for (const std::pair< 5361c8fba97SJames Feist std::string, 5377e860f15SJohn Edward Broadbent std::vector<std::pair<std::string, 5387e860f15SJohn Edward Broadbent std::vector<std::string>>>>& 5391214b7e7SGunnar Mills object : subtree) 5401c8fba97SJames Feist { 5411c8fba97SJames Feist const std::string& path = object.first; 5421c8fba97SJames Feist const std::vector< 5431214b7e7SGunnar Mills std::pair<std::string, std::vector<std::string>>>& 5441214b7e7SGunnar Mills connectionNames = object.second; 5451c8fba97SJames Feist 5461c8fba97SJames Feist if (!boost::ends_with(path, chassisId)) 5471c8fba97SJames Feist { 5481c8fba97SJames Feist continue; 5491c8fba97SJames Feist } 5501c8fba97SJames Feist 5511c8fba97SJames Feist if (connectionNames.size() < 1) 5521c8fba97SJames Feist { 5531c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 5541c8fba97SJames Feist continue; 5551c8fba97SJames Feist } 5561c8fba97SJames Feist 55723a21a1cSEd Tanous const std::vector<std::string>& interfaces3 = 5581c8fba97SJames Feist connectionNames[0].second; 5591c8fba97SJames Feist 5601c8fba97SJames Feist const std::array<const char*, 2> hasIndicatorLed = { 5611c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 5621c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board." 5631c8fba97SJames Feist "Motherboard"}; 5641c8fba97SJames Feist bool indicatorChassis = false; 5651c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 5661c8fba97SJames Feist { 5677e860f15SJohn Edward Broadbent if (std::find(interfaces3.begin(), 5687e860f15SJohn Edward Broadbent interfaces3.end(), 56923a21a1cSEd Tanous interface) != interfaces3.end()) 5701c8fba97SJames Feist { 5711c8fba97SJames Feist indicatorChassis = true; 5721c8fba97SJames Feist break; 5731c8fba97SJames Feist } 5741c8fba97SJames Feist } 5759f8bfa7cSGunnar Mills if (locationIndicatorActive) 5769f8bfa7cSGunnar Mills { 5779f8bfa7cSGunnar Mills if (indicatorChassis) 5789f8bfa7cSGunnar Mills { 5799f8bfa7cSGunnar Mills setLocationIndicatorActive( 5809f8bfa7cSGunnar Mills asyncResp, *locationIndicatorActive); 5819f8bfa7cSGunnar Mills } 5829f8bfa7cSGunnar Mills else 5839f8bfa7cSGunnar Mills { 5849f8bfa7cSGunnar Mills messages::propertyUnknown( 5859f8bfa7cSGunnar Mills asyncResp->res, "LocationIndicatorActive"); 5869f8bfa7cSGunnar Mills } 5879f8bfa7cSGunnar Mills } 5889f8bfa7cSGunnar Mills if (indicatorLed) 5899f8bfa7cSGunnar Mills { 5901c8fba97SJames Feist if (indicatorChassis) 5911c8fba97SJames Feist { 592f23b7296SEd Tanous setIndicatorLedState(asyncResp, *indicatorLed); 5931c8fba97SJames Feist } 5941c8fba97SJames Feist else 5951c8fba97SJames Feist { 5961c8fba97SJames Feist messages::propertyUnknown(asyncResp->res, 5971c8fba97SJames Feist "IndicatorLED"); 5981c8fba97SJames Feist } 5991c8fba97SJames Feist } 6001c8fba97SJames Feist return; 6011c8fba97SJames Feist } 6021c8fba97SJames Feist 6031c8fba97SJames Feist messages::resourceNotFound( 6049f8bfa7cSGunnar Mills asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId); 6051c8fba97SJames Feist }, 6061c8fba97SJames Feist "xyz.openbmc_project.ObjectMapper", 6071c8fba97SJames Feist "/xyz/openbmc_project/object_mapper", 6081c8fba97SJames Feist "xyz.openbmc_project.ObjectMapper", "GetSubTree", 6091c8fba97SJames Feist "/xyz/openbmc_project/inventory", 0, interfaces); 6107e860f15SJohn Edward Broadbent }); 6111c8fba97SJames Feist } 612dd99e04bSP.K. Lee 6138d1b46d7Szhanghch05 inline void 6148d1b46d7Szhanghch05 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 615dd99e04bSP.K. Lee { 616c3b3c92aSVijay Khemka const char* busName = "xyz.openbmc_project.ObjectMapper"; 617c3b3c92aSVijay Khemka const char* path = "/xyz/openbmc_project/object_mapper"; 618c3b3c92aSVijay Khemka const char* interface = "xyz.openbmc_project.ObjectMapper"; 619c3b3c92aSVijay Khemka const char* method = "GetSubTreePaths"; 620c3b3c92aSVijay Khemka 621c3b3c92aSVijay Khemka const std::array<const char*, 1> interfaces = { 622c3b3c92aSVijay Khemka "xyz.openbmc_project.State.Chassis"}; 623c3b3c92aSVijay Khemka 624c3b3c92aSVijay Khemka // Use mapper to get subtree paths. 625c3b3c92aSVijay Khemka crow::connections::systemBus->async_method_call( 626c3b3c92aSVijay Khemka [asyncResp](const boost::system::error_code ec, 627c3b3c92aSVijay Khemka const std::vector<std::string>& chassisList) { 628c3b3c92aSVijay Khemka if (ec) 629c3b3c92aSVijay Khemka { 630c3b3c92aSVijay Khemka BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec; 631c3b3c92aSVijay Khemka messages::internalError(asyncResp->res); 632c3b3c92aSVijay Khemka return; 633c3b3c92aSVijay Khemka } 634c3b3c92aSVijay Khemka 635dd99e04bSP.K. Lee const char* processName = "xyz.openbmc_project.State.Chassis"; 636dd99e04bSP.K. Lee const char* interfaceName = "xyz.openbmc_project.State.Chassis"; 637dd99e04bSP.K. Lee const char* destProperty = "RequestedPowerTransition"; 638dd99e04bSP.K. Lee const std::string propertyValue = 639dd99e04bSP.K. Lee "xyz.openbmc_project.State.Chassis.Transition.PowerCycle"; 640c3b3c92aSVijay Khemka std::string objectPath = 641c3b3c92aSVijay Khemka "/xyz/openbmc_project/state/chassis_system0"; 642c3b3c92aSVijay Khemka 643c3b3c92aSVijay Khemka /* Look for system reset chassis path */ 644c3b3c92aSVijay Khemka if ((std::find(chassisList.begin(), chassisList.end(), 645c3b3c92aSVijay Khemka objectPath)) == chassisList.end()) 646c3b3c92aSVijay Khemka { 647c3b3c92aSVijay Khemka /* We prefer to reset the full chassis_system, but if it doesn't 648c3b3c92aSVijay Khemka * exist on some platforms, fall back to a host-only power reset 649c3b3c92aSVijay Khemka */ 650c3b3c92aSVijay Khemka objectPath = "/xyz/openbmc_project/state/chassis0"; 651c3b3c92aSVijay Khemka } 652dd99e04bSP.K. Lee 653dd99e04bSP.K. Lee crow::connections::systemBus->async_method_call( 654dd99e04bSP.K. Lee [asyncResp](const boost::system::error_code ec) { 655dd99e04bSP.K. Lee // Use "Set" method to set the property value. 656dd99e04bSP.K. Lee if (ec) 657dd99e04bSP.K. Lee { 658c3b3c92aSVijay Khemka BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: " 659c3b3c92aSVijay Khemka << ec; 660dd99e04bSP.K. Lee messages::internalError(asyncResp->res); 661dd99e04bSP.K. Lee return; 662dd99e04bSP.K. Lee } 663dd99e04bSP.K. Lee 664dd99e04bSP.K. Lee messages::success(asyncResp->res); 665dd99e04bSP.K. Lee }, 666c3b3c92aSVijay Khemka processName, objectPath, "org.freedesktop.DBus.Properties", 667c3b3c92aSVijay Khemka "Set", interfaceName, destProperty, 668c3b3c92aSVijay Khemka std::variant<std::string>{propertyValue}); 669c3b3c92aSVijay Khemka }, 670c3b3c92aSVijay Khemka busName, path, interface, method, "/", 0, interfaces); 671dd99e04bSP.K. Lee } 672dd99e04bSP.K. Lee 673dd99e04bSP.K. Lee /** 674dd99e04bSP.K. Lee * ChassisResetAction class supports the POST method for the Reset 675dd99e04bSP.K. Lee * action. 676dd99e04bSP.K. Lee * Function handles POST method request. 677dd99e04bSP.K. Lee * Analyzes POST body before sending Reset request data to D-Bus. 678dd99e04bSP.K. Lee */ 6797e860f15SJohn Edward Broadbent 6807e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetAction(App& app) 681dd99e04bSP.K. Lee { 6827e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/") 683ed398213SEd Tanous .privileges(redfish::privileges::postChassis) 6847e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 6857e860f15SJohn Edward Broadbent [](const crow::Request& req, 6867e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6877e860f15SJohn Edward Broadbent const std::string&) { 688dd99e04bSP.K. Lee BMCWEB_LOG_DEBUG << "Post Chassis Reset."; 689dd99e04bSP.K. Lee 690dd99e04bSP.K. Lee std::string resetType; 691dd99e04bSP.K. Lee 6927e860f15SJohn Edward Broadbent if (!json_util::readJson(req, asyncResp->res, "ResetType", 6937e860f15SJohn Edward Broadbent resetType)) 694dd99e04bSP.K. Lee { 695dd99e04bSP.K. Lee return; 696dd99e04bSP.K. Lee } 697dd99e04bSP.K. Lee 698dd99e04bSP.K. Lee if (resetType != "PowerCycle") 699dd99e04bSP.K. Lee { 700dd99e04bSP.K. Lee BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: " 701dd99e04bSP.K. Lee << resetType; 7027e860f15SJohn Edward Broadbent messages::actionParameterNotSupported( 7037e860f15SJohn Edward Broadbent asyncResp->res, resetType, "ResetType"); 704dd99e04bSP.K. Lee 705dd99e04bSP.K. Lee return; 706dd99e04bSP.K. Lee } 707dd99e04bSP.K. Lee doChassisPowerCycle(asyncResp); 7087e860f15SJohn Edward Broadbent }); 709dd99e04bSP.K. Lee } 7101cb1a9e6SAppaRao Puli 7111cb1a9e6SAppaRao Puli /** 7121cb1a9e6SAppaRao Puli * ChassisResetActionInfo derived class for delivering Chassis 7131cb1a9e6SAppaRao Puli * ResetType AllowableValues using ResetInfo schema. 7141cb1a9e6SAppaRao Puli */ 7157e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetActionInfo(App& app) 7161cb1a9e6SAppaRao Puli { 7177e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/") 718ed398213SEd Tanous .privileges(redfish::privileges::getActionInfo) 7197e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 7207e860f15SJohn Edward Broadbent [](const crow::Request&, 7217e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 7227e860f15SJohn Edward Broadbent const std::string& chassisId) 7231cb1a9e6SAppaRao Puli 7241cb1a9e6SAppaRao Puli { 7258d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 7268d1b46d7Szhanghch05 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"}, 7278d1b46d7Szhanghch05 {"@odata.id", 7288d1b46d7Szhanghch05 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"}, 7291cb1a9e6SAppaRao Puli {"Name", "Reset Action Info"}, 7301cb1a9e6SAppaRao Puli {"Id", "ResetActionInfo"}, 7311cb1a9e6SAppaRao Puli {"Parameters", 7321cb1a9e6SAppaRao Puli {{{"Name", "ResetType"}, 7331cb1a9e6SAppaRao Puli {"Required", true}, 7341cb1a9e6SAppaRao Puli {"DataType", "String"}, 7351cb1a9e6SAppaRao Puli {"AllowableValues", {"PowerCycle"}}}}}}; 7367e860f15SJohn Edward Broadbent }); 7371cb1a9e6SAppaRao Puli } 7381cb1a9e6SAppaRao Puli 739e37f8451SRapkiewicz, Pawel } // namespace redfish 740