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" 20e37f8451SRapkiewicz, Pawel #include "node.hpp" 211abe55efSEd Tanous 22e37f8451SRapkiewicz, Pawel #include <boost/container/flat_map.hpp> 2302f6ff19SGunnar Mills #include <utils/collection.hpp> 241214b7e7SGunnar Mills 25abf2add6SEd Tanous #include <variant> 26e37f8451SRapkiewicz, Pawel 271abe55efSEd Tanous namespace redfish 281abe55efSEd Tanous { 29e37f8451SRapkiewicz, Pawel 30e37f8451SRapkiewicz, Pawel /** 31beeca0aeSGunnar Mills * @brief Retrieves chassis state properties over dbus 32beeca0aeSGunnar Mills * 33beeca0aeSGunnar Mills * @param[in] aResp - Shared pointer for completing asynchronous calls. 34beeca0aeSGunnar Mills * 35beeca0aeSGunnar Mills * @return None. 36beeca0aeSGunnar Mills */ 37*8d1b46d7Szhanghch05 inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp) 38beeca0aeSGunnar Mills { 39beeca0aeSGunnar Mills crow::connections::systemBus->async_method_call( 40beeca0aeSGunnar Mills [aResp{std::move(aResp)}]( 41beeca0aeSGunnar Mills const boost::system::error_code ec, 42beeca0aeSGunnar Mills const std::variant<std::string>& chassisState) { 43beeca0aeSGunnar Mills if (ec) 44beeca0aeSGunnar Mills { 45beeca0aeSGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 46beeca0aeSGunnar Mills messages::internalError(aResp->res); 47beeca0aeSGunnar Mills return; 48beeca0aeSGunnar Mills } 49beeca0aeSGunnar Mills 50beeca0aeSGunnar Mills const std::string* s = std::get_if<std::string>(&chassisState); 51beeca0aeSGunnar Mills BMCWEB_LOG_DEBUG << "Chassis state: " << *s; 52beeca0aeSGunnar Mills if (s != nullptr) 53beeca0aeSGunnar Mills { 54beeca0aeSGunnar Mills // Verify Chassis State 55beeca0aeSGunnar Mills if (*s == "xyz.openbmc_project.State.Chassis.PowerState.On") 56beeca0aeSGunnar Mills { 57beeca0aeSGunnar Mills aResp->res.jsonValue["PowerState"] = "On"; 58beeca0aeSGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Enabled"; 59beeca0aeSGunnar Mills } 60beeca0aeSGunnar Mills else if (*s == 61beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis.PowerState.Off") 62beeca0aeSGunnar Mills { 63beeca0aeSGunnar Mills aResp->res.jsonValue["PowerState"] = "Off"; 64beeca0aeSGunnar Mills aResp->res.jsonValue["Status"]["State"] = "StandbyOffline"; 65beeca0aeSGunnar Mills } 66beeca0aeSGunnar Mills } 67beeca0aeSGunnar Mills }, 68beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis", 69beeca0aeSGunnar Mills "/xyz/openbmc_project/state/chassis0", 70beeca0aeSGunnar Mills "org.freedesktop.DBus.Properties", "Get", 71beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis", "CurrentPowerState"); 72beeca0aeSGunnar Mills } 73beeca0aeSGunnar Mills 74beeca0aeSGunnar Mills /** 75e37f8451SRapkiewicz, Pawel * DBus types primitives for several generic DBus interfaces 76e37f8451SRapkiewicz, Pawel * TODO(Pawel) consider move this to separate file into boost::dbus 77e37f8451SRapkiewicz, Pawel */ 7855c7b7a2SEd Tanous // Note, this is not a very useful Variant, but because it isn't used to get 79aa2e59c1SEd Tanous // values, it should be as simple as possible 80aa2e59c1SEd Tanous // TODO(ed) invent a nullvariant type 815fd7ba65SCheng C Yang using VariantType = std::variant<bool, std::string, uint64_t, uint32_t>; 82aa2e59c1SEd Tanous using ManagedObjectsType = std::vector<std::pair< 83aa2e59c1SEd Tanous sdbusplus::message::object_path, 84aa2e59c1SEd Tanous std::vector<std::pair<std::string, 85aa2e59c1SEd Tanous std::vector<std::pair<std::string, VariantType>>>>>>; 86e37f8451SRapkiewicz, Pawel 87aa2e59c1SEd Tanous using PropertiesType = boost::container::flat_map<std::string, VariantType>; 88e37f8451SRapkiewicz, Pawel 89*8d1b46d7Szhanghch05 inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp, 90c181942fSQiang XU const std::string& service, 91c181942fSQiang XU const std::string& objPath) 92c181942fSQiang XU { 93c181942fSQiang XU BMCWEB_LOG_DEBUG << "Get intrusion status by service \n"; 94c181942fSQiang XU 95c181942fSQiang XU crow::connections::systemBus->async_method_call( 96c181942fSQiang XU [aResp{std::move(aResp)}](const boost::system::error_code ec, 97c181942fSQiang XU const std::variant<std::string>& value) { 98c181942fSQiang XU if (ec) 99c181942fSQiang XU { 1004e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 101c181942fSQiang XU // mandatory property 102c181942fSQiang XU BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n"; 103c181942fSQiang XU return; 104c181942fSQiang XU } 105c181942fSQiang XU 106c181942fSQiang XU const std::string* status = std::get_if<std::string>(&value); 107c181942fSQiang XU 108c181942fSQiang XU if (status == nullptr) 109c181942fSQiang XU { 110c181942fSQiang XU BMCWEB_LOG_ERROR << "intrusion status read error \n"; 111c181942fSQiang XU return; 112c181942fSQiang XU } 113c181942fSQiang XU 114c181942fSQiang XU aResp->res.jsonValue["PhysicalSecurity"] = { 115c181942fSQiang XU {"IntrusionSensorNumber", 1}, {"IntrusionSensor", *status}}; 116c181942fSQiang XU }, 117c181942fSQiang XU service, objPath, "org.freedesktop.DBus.Properties", "Get", 118c181942fSQiang XU "xyz.openbmc_project.Chassis.Intrusion", "Status"); 119c181942fSQiang XU } 120c181942fSQiang XU 121c181942fSQiang XU /** 122c181942fSQiang XU * Retrieves physical security properties over dbus 123c181942fSQiang XU */ 124*8d1b46d7Szhanghch05 inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp) 125c181942fSQiang XU { 126c181942fSQiang XU crow::connections::systemBus->async_method_call( 127c181942fSQiang XU [aResp{std::move(aResp)}]( 128c181942fSQiang XU const boost::system::error_code ec, 129c181942fSQiang XU const std::vector<std::pair< 130c181942fSQiang XU std::string, 1311214b7e7SGunnar Mills std::vector<std::pair<std::string, std::vector<std::string>>>>>& 1321214b7e7SGunnar Mills subtree) { 133c181942fSQiang XU if (ec) 134c181942fSQiang XU { 1354e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 136c181942fSQiang XU // mandatory property 137c181942fSQiang XU BMCWEB_LOG_ERROR << "DBUS error: no matched iface " << ec 138c181942fSQiang XU << "\n"; 139c181942fSQiang XU return; 140c181942fSQiang XU } 141c181942fSQiang XU // Iterate over all retrieved ObjectPaths. 142c181942fSQiang XU for (const auto& object : subtree) 143c181942fSQiang XU { 144c181942fSQiang XU for (const auto& service : object.second) 145c181942fSQiang XU { 146c181942fSQiang XU getIntrusionByService(aResp, service.first, object.first); 147c181942fSQiang XU return; 148c181942fSQiang XU } 149c181942fSQiang XU } 150c181942fSQiang XU }, 151c181942fSQiang XU "xyz.openbmc_project.ObjectMapper", 152c181942fSQiang XU "/xyz/openbmc_project/object_mapper", 153c181942fSQiang XU "xyz.openbmc_project.ObjectMapper", "GetSubTree", 154271584abSEd Tanous "/xyz/openbmc_project/Intrusion", 1, 155c181942fSQiang XU std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"}); 156c181942fSQiang XU } 157c181942fSQiang XU 158e37f8451SRapkiewicz, Pawel /** 159e37f8451SRapkiewicz, Pawel * ChassisCollection derived class for delivering Chassis Collection Schema 160e37f8451SRapkiewicz, Pawel */ 1611abe55efSEd Tanous class ChassisCollection : public Node 1621abe55efSEd Tanous { 163e37f8451SRapkiewicz, Pawel public: 16452cc112dSEd Tanous ChassisCollection(App& app) : Node(app, "/redfish/v1/Chassis/") 1651abe55efSEd Tanous { 166e0d918bcSEd Tanous entityPrivileges = { 167e0d918bcSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 168e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 169e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 170e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 171e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 172e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 173e37f8451SRapkiewicz, Pawel } 174e37f8451SRapkiewicz, Pawel 175e37f8451SRapkiewicz, Pawel private: 176e37f8451SRapkiewicz, Pawel /** 177e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 178e37f8451SRapkiewicz, Pawel */ 179*8d1b46d7Szhanghch05 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 180*8d1b46d7Szhanghch05 const crow::Request&, const std::vector<std::string>&) override 1811abe55efSEd Tanous { 182*8d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 183*8d1b46d7Szhanghch05 "#ChassisCollection.ChassisCollection"; 184*8d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 185*8d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 186e37f8451SRapkiewicz, Pawel 18702f6ff19SGunnar Mills collection_util::getCollectionMembers( 18802f6ff19SGunnar Mills asyncResp, "/redfish/v1/Chassis", 18902f6ff19SGunnar Mills {"xyz.openbmc_project.Inventory.Item.Board", 19002f6ff19SGunnar Mills "xyz.openbmc_project.Inventory.Item.Chassis"}); 19162d5e2e4SEd Tanous } 192e37f8451SRapkiewicz, Pawel }; 193e37f8451SRapkiewicz, Pawel 194e37f8451SRapkiewicz, Pawel /** 195e37f8451SRapkiewicz, Pawel * Chassis override class for delivering Chassis Schema 196e37f8451SRapkiewicz, Pawel */ 1971abe55efSEd Tanous class Chassis : public Node 1981abe55efSEd Tanous { 199e37f8451SRapkiewicz, Pawel public: 20052cc112dSEd Tanous Chassis(App& app) : Node(app, "/redfish/v1/Chassis/<str>/", std::string()) 2011abe55efSEd Tanous { 202e0d918bcSEd Tanous entityPrivileges = { 203e0d918bcSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 204e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 205e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 206e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 207e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 208e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 209e37f8451SRapkiewicz, Pawel } 210e37f8451SRapkiewicz, Pawel 211e37f8451SRapkiewicz, Pawel private: 212e37f8451SRapkiewicz, Pawel /** 213e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 214e37f8451SRapkiewicz, Pawel */ 215*8d1b46d7Szhanghch05 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 216*8d1b46d7Szhanghch05 const crow::Request&, 2171abe55efSEd Tanous const std::vector<std::string>& params) override 2181abe55efSEd Tanous { 219adc4f0dbSShawn McCarney const std::array<const char*, 2> interfaces = { 220734bfe90SGunnar Mills "xyz.openbmc_project.Inventory.Item.Board", 221adc4f0dbSShawn McCarney "xyz.openbmc_project.Inventory.Item.Chassis"}; 222734bfe90SGunnar Mills 223e37f8451SRapkiewicz, Pawel // Check if there is required param, truly entering this shall be 224e37f8451SRapkiewicz, Pawel // impossible. 2251abe55efSEd Tanous if (params.size() != 1) 2261abe55efSEd Tanous { 227*8d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 228e37f8451SRapkiewicz, Pawel return; 229e37f8451SRapkiewicz, Pawel } 23099cffd7fSShawn McCarney const std::string& chassisId = params[0]; 231e37f8451SRapkiewicz, Pawel 23255c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 23362d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 23462d5e2e4SEd Tanous const boost::system::error_code ec, 2351c8fba97SJames Feist const crow::openbmc_mapper::GetSubTreeType& subtree) { 23662d5e2e4SEd Tanous if (ec) 2371abe55efSEd Tanous { 238f12894f8SJason M. Bills messages::internalError(asyncResp->res); 239daf36e2eSEd Tanous return; 240daf36e2eSEd Tanous } 241daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 2421abe55efSEd Tanous for (const std::pair< 2431abe55efSEd Tanous std::string, 2441abe55efSEd Tanous std::vector< 2451214b7e7SGunnar Mills std::pair<std::string, std::vector<std::string>>>>& 2461214b7e7SGunnar Mills object : subtree) 2471abe55efSEd Tanous { 248daf36e2eSEd Tanous const std::string& path = object.first; 2491abe55efSEd Tanous const std::vector< 2501214b7e7SGunnar Mills std::pair<std::string, std::vector<std::string>>>& 2511214b7e7SGunnar Mills connectionNames = object.second; 252e0d918bcSEd Tanous 2531abe55efSEd Tanous if (!boost::ends_with(path, chassisId)) 2541abe55efSEd Tanous { 255daf36e2eSEd Tanous continue; 256daf36e2eSEd Tanous } 25726f03899SShawn McCarney 258b49ac873SJames Feist auto health = std::make_shared<HealthPopulate>(asyncResp); 259b49ac873SJames Feist 260b49ac873SJames Feist crow::connections::systemBus->async_method_call( 26123a21a1cSEd Tanous [health](const boost::system::error_code ec2, 262b49ac873SJames Feist std::variant<std::vector<std::string>>& resp) { 26323a21a1cSEd Tanous if (ec2) 264b49ac873SJames Feist { 265b49ac873SJames Feist return; // no sensors = no failures 266b49ac873SJames Feist } 267b49ac873SJames Feist std::vector<std::string>* data = 268b49ac873SJames Feist std::get_if<std::vector<std::string>>(&resp); 269b49ac873SJames Feist if (data == nullptr) 270b49ac873SJames Feist { 271b49ac873SJames Feist return; 272b49ac873SJames Feist } 273b49ac873SJames Feist health->inventory = std::move(*data); 274b49ac873SJames Feist }, 275b49ac873SJames Feist "xyz.openbmc_project.ObjectMapper", 276b49ac873SJames Feist path + "/all_sensors", 277b49ac873SJames Feist "org.freedesktop.DBus.Properties", "Get", 278b49ac873SJames Feist "xyz.openbmc_project.Association", "endpoints"); 279b49ac873SJames Feist 280b49ac873SJames Feist health->populate(); 281b49ac873SJames Feist 2821abe55efSEd Tanous if (connectionNames.size() < 1) 2831abe55efSEd Tanous { 2841c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 285e0d918bcSEd Tanous continue; 286daf36e2eSEd Tanous } 287e0d918bcSEd Tanous 28849c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.type"] = 2899f8bfa7cSGunnar Mills "#Chassis.v1_14_0.Chassis"; 29049c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.id"] = 29149c53ac9SJohnathan Mantey "/redfish/v1/Chassis/" + chassisId; 29249c53ac9SJohnathan Mantey asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 29349c53ac9SJohnathan Mantey asyncResp->res.jsonValue["ChassisType"] = "RackMount"; 294dd99e04bSP.K. Lee asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] = { 295dd99e04bSP.K. Lee {"target", "/redfish/v1/Chassis/" + chassisId + 296dd99e04bSP.K. Lee "/Actions/Chassis.Reset"}, 2971cb1a9e6SAppaRao Puli {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" + 2981cb1a9e6SAppaRao Puli chassisId + 2991cb1a9e6SAppaRao Puli "/ResetActionInfo"}}; 300adbe192aSJason M. Bills asyncResp->res.jsonValue["PCIeDevices"] = { 301adbe192aSJason M. Bills {"@odata.id", 302adbe192aSJason M. Bills "/redfish/v1/Systems/system/PCIeDevices"}}; 30349c53ac9SJohnathan Mantey 30449c53ac9SJohnathan Mantey const std::string& connectionName = 30549c53ac9SJohnathan Mantey connectionNames[0].first; 3061c8fba97SJames Feist 30723a21a1cSEd Tanous const std::vector<std::string>& interfaces2 = 3081c8fba97SJames Feist connectionNames[0].second; 3091c8fba97SJames Feist const std::array<const char*, 2> hasIndicatorLed = { 3101c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 3111c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 3121c8fba97SJames Feist 3131c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 3141c8fba97SJames Feist { 31523a21a1cSEd Tanous if (std::find(interfaces2.begin(), interfaces2.end(), 31623a21a1cSEd Tanous interface) != interfaces2.end()) 3171c8fba97SJames Feist { 3181c8fba97SJames Feist getIndicatorLedState(asyncResp); 3199f8bfa7cSGunnar Mills getLocationIndicatorActive(asyncResp); 3201c8fba97SJames Feist break; 3211c8fba97SJames Feist } 3221c8fba97SJames Feist } 3231c8fba97SJames Feist 32488ad7f03SSunnySrivastava1984 const std::string locationInterface = 32588ad7f03SSunnySrivastava1984 "xyz.openbmc_project.Inventory.Decorator.LocationCode"; 32688ad7f03SSunnySrivastava1984 if (std::find(interfaces2.begin(), interfaces2.end(), 32788ad7f03SSunnySrivastava1984 locationInterface) != interfaces2.end()) 32888ad7f03SSunnySrivastava1984 { 32988ad7f03SSunnySrivastava1984 crow::connections::systemBus->async_method_call( 33088ad7f03SSunnySrivastava1984 [asyncResp, chassisId(std::string(chassisId))]( 33188ad7f03SSunnySrivastava1984 const boost::system::error_code ec, 33288ad7f03SSunnySrivastava1984 const std::variant<std::string>& property) { 33388ad7f03SSunnySrivastava1984 if (ec) 33488ad7f03SSunnySrivastava1984 { 33588ad7f03SSunnySrivastava1984 BMCWEB_LOG_DEBUG 33688ad7f03SSunnySrivastava1984 << "DBUS response error for Location"; 33788ad7f03SSunnySrivastava1984 messages::internalError(asyncResp->res); 33888ad7f03SSunnySrivastava1984 return; 33988ad7f03SSunnySrivastava1984 } 34088ad7f03SSunnySrivastava1984 34188ad7f03SSunnySrivastava1984 const std::string* value = 34288ad7f03SSunnySrivastava1984 std::get_if<std::string>(&property); 34388ad7f03SSunnySrivastava1984 if (value == nullptr) 34488ad7f03SSunnySrivastava1984 { 34588ad7f03SSunnySrivastava1984 BMCWEB_LOG_DEBUG << "Null value returned " 34688ad7f03SSunnySrivastava1984 "for locaton code"; 34788ad7f03SSunnySrivastava1984 messages::internalError(asyncResp->res); 34888ad7f03SSunnySrivastava1984 return; 34988ad7f03SSunnySrivastava1984 } 35088ad7f03SSunnySrivastava1984 asyncResp->res 35188ad7f03SSunnySrivastava1984 .jsonValue["Location"]["PartLocation"] 35288ad7f03SSunnySrivastava1984 ["ServiceLabel"] = *value; 35388ad7f03SSunnySrivastava1984 }, 35488ad7f03SSunnySrivastava1984 connectionName, path, 35588ad7f03SSunnySrivastava1984 "org.freedesktop.DBus.Properties", "Get", 35688ad7f03SSunnySrivastava1984 locationInterface, "LocationCode"); 35788ad7f03SSunnySrivastava1984 } 35888ad7f03SSunnySrivastava1984 35955c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 36062d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 36190728b54SEd Tanous const boost::system::error_code /*ec2*/, 3621abe55efSEd Tanous const std::vector<std::pair< 3631abe55efSEd Tanous std::string, VariantType>>& propertiesList) { 3641214b7e7SGunnar Mills for (const std::pair<std::string, VariantType>& 3651214b7e7SGunnar Mills property : propertiesList) 3661abe55efSEd Tanous { 36799cffd7fSShawn McCarney // Store DBus properties that are also Redfish 36899cffd7fSShawn McCarney // properties with same name and a string value 36999cffd7fSShawn McCarney const std::string& propertyName = 37099cffd7fSShawn McCarney property.first; 37199cffd7fSShawn McCarney if ((propertyName == "PartNumber") || 37299cffd7fSShawn McCarney (propertyName == "SerialNumber") || 37399cffd7fSShawn McCarney (propertyName == "Manufacturer") || 37499cffd7fSShawn McCarney (propertyName == "Model")) 37599cffd7fSShawn McCarney { 376daf36e2eSEd Tanous const std::string* value = 37799cffd7fSShawn McCarney std::get_if<std::string>( 37899cffd7fSShawn McCarney &property.second); 3791abe55efSEd Tanous if (value != nullptr) 3801abe55efSEd Tanous { 38199cffd7fSShawn McCarney asyncResp->res.jsonValue[propertyName] = 38262d5e2e4SEd Tanous *value; 383daf36e2eSEd Tanous } 384daf36e2eSEd Tanous } 38599cffd7fSShawn McCarney } 38662d5e2e4SEd Tanous asyncResp->res.jsonValue["Name"] = chassisId; 38762d5e2e4SEd Tanous asyncResp->res.jsonValue["Id"] = chassisId; 38862d5e2e4SEd Tanous asyncResp->res.jsonValue["Thermal"] = { 3891abe55efSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 3901abe55efSEd Tanous chassisId + "/Thermal"}}; 3912474adfaSEd Tanous // Power object 3922474adfaSEd Tanous asyncResp->res.jsonValue["Power"] = { 3932474adfaSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 3942474adfaSEd Tanous chassisId + "/Power"}}; 39595a3ecadSAnthony Wilson // SensorCollection 39695a3ecadSAnthony Wilson asyncResp->res.jsonValue["Sensors"] = { 39795a3ecadSAnthony Wilson {"@odata.id", "/redfish/v1/Chassis/" + 39895a3ecadSAnthony Wilson chassisId + "/Sensors"}}; 399029573d4SEd Tanous asyncResp->res.jsonValue["Status"] = { 400029573d4SEd Tanous {"State", "Enabled"}, 401029573d4SEd Tanous }; 4022474adfaSEd Tanous 403029573d4SEd Tanous asyncResp->res 404029573d4SEd Tanous .jsonValue["Links"]["ComputerSystems"] = { 405029573d4SEd Tanous {{"@odata.id", "/redfish/v1/Systems/system"}}}; 406029573d4SEd Tanous asyncResp->res.jsonValue["Links"]["ManagedBy"] = { 407029573d4SEd Tanous {{"@odata.id", "/redfish/v1/Managers/bmc"}}}; 408beeca0aeSGunnar Mills getChassisState(asyncResp); 409daf36e2eSEd Tanous }, 410daf36e2eSEd Tanous connectionName, path, "org.freedesktop.DBus.Properties", 4111abe55efSEd Tanous "GetAll", 4121abe55efSEd Tanous "xyz.openbmc_project.Inventory.Decorator.Asset"); 413daf36e2eSEd Tanous return; 414daf36e2eSEd Tanous } 415e0d918bcSEd Tanous 416daf36e2eSEd Tanous // Couldn't find an object with that name. return an error 417f12894f8SJason M. Bills messages::resourceNotFound( 4189f8bfa7cSGunnar Mills asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId); 419daf36e2eSEd Tanous }, 420daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", 421daf36e2eSEd Tanous "/xyz/openbmc_project/object_mapper", 422daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTree", 423271584abSEd Tanous "/xyz/openbmc_project/inventory", 0, interfaces); 424c181942fSQiang XU 425c181942fSQiang XU getPhysicalSecurityData(asyncResp); 426e37f8451SRapkiewicz, Pawel } 4271c8fba97SJames Feist 428*8d1b46d7Szhanghch05 void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 429*8d1b46d7Szhanghch05 const crow::Request& req, 4301c8fba97SJames Feist const std::vector<std::string>& params) override 4311c8fba97SJames Feist { 4329f8bfa7cSGunnar Mills std::optional<bool> locationIndicatorActive; 4331c8fba97SJames Feist std::optional<std::string> indicatorLed; 4341c8fba97SJames Feist 4351c8fba97SJames Feist if (params.size() != 1) 4361c8fba97SJames Feist { 4371c8fba97SJames Feist return; 4381c8fba97SJames Feist } 4391c8fba97SJames Feist 440*8d1b46d7Szhanghch05 if (!json_util::readJson(req, asyncResp->res, "LocationIndicatorActive", 4419f8bfa7cSGunnar Mills locationIndicatorActive, "IndicatorLED", 4429f8bfa7cSGunnar Mills indicatorLed)) 4431c8fba97SJames Feist { 4441c8fba97SJames Feist return; 4451c8fba97SJames Feist } 4461c8fba97SJames Feist 4479f8bfa7cSGunnar Mills // TODO (Gunnar): Remove IndicatorLED after enough time has passed 4489f8bfa7cSGunnar Mills if (!locationIndicatorActive && !indicatorLed) 4491c8fba97SJames Feist { 4501c8fba97SJames Feist return; // delete this when we support more patch properties 4511c8fba97SJames Feist } 452d6aa0093SGunnar Mills if (indicatorLed) 453d6aa0093SGunnar Mills { 454*8d1b46d7Szhanghch05 asyncResp->res.addHeader(boost::beast::http::field::warning, 455d6aa0093SGunnar Mills "299 - \"IndicatorLED is deprecated. Use " 456d6aa0093SGunnar Mills "LocationIndicatorActive instead.\""); 457d6aa0093SGunnar Mills } 4581c8fba97SJames Feist 4591c8fba97SJames Feist const std::array<const char*, 2> interfaces = { 4601c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board", 4611c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Chassis"}; 4621c8fba97SJames Feist 4631c8fba97SJames Feist const std::string& chassisId = params[0]; 4641c8fba97SJames Feist 4651c8fba97SJames Feist crow::connections::systemBus->async_method_call( 4669f8bfa7cSGunnar Mills [asyncResp, chassisId, locationIndicatorActive, indicatorLed]( 4671c8fba97SJames Feist const boost::system::error_code ec, 4681c8fba97SJames Feist const crow::openbmc_mapper::GetSubTreeType& subtree) { 4691c8fba97SJames Feist if (ec) 4701c8fba97SJames Feist { 4711c8fba97SJames Feist messages::internalError(asyncResp->res); 4721c8fba97SJames Feist return; 4731c8fba97SJames Feist } 4741c8fba97SJames Feist 4751c8fba97SJames Feist // Iterate over all retrieved ObjectPaths. 4761c8fba97SJames Feist for (const std::pair< 4771c8fba97SJames Feist std::string, 4781c8fba97SJames Feist std::vector< 4791214b7e7SGunnar Mills std::pair<std::string, std::vector<std::string>>>>& 4801214b7e7SGunnar Mills object : subtree) 4811c8fba97SJames Feist { 4821c8fba97SJames Feist const std::string& path = object.first; 4831c8fba97SJames Feist const std::vector< 4841214b7e7SGunnar Mills std::pair<std::string, std::vector<std::string>>>& 4851214b7e7SGunnar Mills connectionNames = object.second; 4861c8fba97SJames Feist 4871c8fba97SJames Feist if (!boost::ends_with(path, chassisId)) 4881c8fba97SJames Feist { 4891c8fba97SJames Feist continue; 4901c8fba97SJames Feist } 4911c8fba97SJames Feist 4921c8fba97SJames Feist if (connectionNames.size() < 1) 4931c8fba97SJames Feist { 4941c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 4951c8fba97SJames Feist continue; 4961c8fba97SJames Feist } 4971c8fba97SJames Feist 49823a21a1cSEd Tanous const std::vector<std::string>& interfaces3 = 4991c8fba97SJames Feist connectionNames[0].second; 5001c8fba97SJames Feist 5011c8fba97SJames Feist const std::array<const char*, 2> hasIndicatorLed = { 5021c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 5031c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board." 5041c8fba97SJames Feist "Motherboard"}; 5051c8fba97SJames Feist bool indicatorChassis = false; 5061c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 5071c8fba97SJames Feist { 5089f8bfa7cSGunnar Mills if (std::find(interfaces3.begin(), interfaces3.end(), 50923a21a1cSEd Tanous interface) != interfaces3.end()) 5101c8fba97SJames Feist { 5111c8fba97SJames Feist indicatorChassis = true; 5121c8fba97SJames Feist break; 5131c8fba97SJames Feist } 5141c8fba97SJames Feist } 5159f8bfa7cSGunnar Mills if (locationIndicatorActive) 5169f8bfa7cSGunnar Mills { 5179f8bfa7cSGunnar Mills if (indicatorChassis) 5189f8bfa7cSGunnar Mills { 5199f8bfa7cSGunnar Mills setLocationIndicatorActive( 5209f8bfa7cSGunnar Mills asyncResp, *locationIndicatorActive); 5219f8bfa7cSGunnar Mills } 5229f8bfa7cSGunnar Mills else 5239f8bfa7cSGunnar Mills { 5249f8bfa7cSGunnar Mills messages::propertyUnknown( 5259f8bfa7cSGunnar Mills asyncResp->res, "LocationIndicatorActive"); 5269f8bfa7cSGunnar Mills } 5279f8bfa7cSGunnar Mills } 5289f8bfa7cSGunnar Mills if (indicatorLed) 5299f8bfa7cSGunnar Mills { 5301c8fba97SJames Feist if (indicatorChassis) 5311c8fba97SJames Feist { 532f23b7296SEd Tanous setIndicatorLedState(asyncResp, *indicatorLed); 5331c8fba97SJames Feist } 5341c8fba97SJames Feist else 5351c8fba97SJames Feist { 5361c8fba97SJames Feist messages::propertyUnknown(asyncResp->res, 5371c8fba97SJames Feist "IndicatorLED"); 5381c8fba97SJames Feist } 5391c8fba97SJames Feist } 5401c8fba97SJames Feist return; 5411c8fba97SJames Feist } 5421c8fba97SJames Feist 5431c8fba97SJames Feist messages::resourceNotFound( 5449f8bfa7cSGunnar Mills asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId); 5451c8fba97SJames Feist }, 5461c8fba97SJames Feist "xyz.openbmc_project.ObjectMapper", 5471c8fba97SJames Feist "/xyz/openbmc_project/object_mapper", 5481c8fba97SJames Feist "xyz.openbmc_project.ObjectMapper", "GetSubTree", 5491c8fba97SJames Feist "/xyz/openbmc_project/inventory", 0, interfaces); 5501c8fba97SJames Feist } 55162d5e2e4SEd Tanous }; 552dd99e04bSP.K. Lee 553*8d1b46d7Szhanghch05 inline void 554*8d1b46d7Szhanghch05 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 555dd99e04bSP.K. Lee { 556c3b3c92aSVijay Khemka const char* busName = "xyz.openbmc_project.ObjectMapper"; 557c3b3c92aSVijay Khemka const char* path = "/xyz/openbmc_project/object_mapper"; 558c3b3c92aSVijay Khemka const char* interface = "xyz.openbmc_project.ObjectMapper"; 559c3b3c92aSVijay Khemka const char* method = "GetSubTreePaths"; 560c3b3c92aSVijay Khemka 561c3b3c92aSVijay Khemka const std::array<const char*, 1> interfaces = { 562c3b3c92aSVijay Khemka "xyz.openbmc_project.State.Chassis"}; 563c3b3c92aSVijay Khemka 564c3b3c92aSVijay Khemka // Use mapper to get subtree paths. 565c3b3c92aSVijay Khemka crow::connections::systemBus->async_method_call( 566c3b3c92aSVijay Khemka [asyncResp](const boost::system::error_code ec, 567c3b3c92aSVijay Khemka const std::vector<std::string>& chassisList) { 568c3b3c92aSVijay Khemka if (ec) 569c3b3c92aSVijay Khemka { 570c3b3c92aSVijay Khemka BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec; 571c3b3c92aSVijay Khemka messages::internalError(asyncResp->res); 572c3b3c92aSVijay Khemka return; 573c3b3c92aSVijay Khemka } 574c3b3c92aSVijay Khemka 575dd99e04bSP.K. Lee const char* processName = "xyz.openbmc_project.State.Chassis"; 576dd99e04bSP.K. Lee const char* interfaceName = "xyz.openbmc_project.State.Chassis"; 577dd99e04bSP.K. Lee const char* destProperty = "RequestedPowerTransition"; 578dd99e04bSP.K. Lee const std::string propertyValue = 579dd99e04bSP.K. Lee "xyz.openbmc_project.State.Chassis.Transition.PowerCycle"; 580c3b3c92aSVijay Khemka std::string objectPath = 581c3b3c92aSVijay Khemka "/xyz/openbmc_project/state/chassis_system0"; 582c3b3c92aSVijay Khemka 583c3b3c92aSVijay Khemka /* Look for system reset chassis path */ 584c3b3c92aSVijay Khemka if ((std::find(chassisList.begin(), chassisList.end(), 585c3b3c92aSVijay Khemka objectPath)) == chassisList.end()) 586c3b3c92aSVijay Khemka { 587c3b3c92aSVijay Khemka /* We prefer to reset the full chassis_system, but if it doesn't 588c3b3c92aSVijay Khemka * exist on some platforms, fall back to a host-only power reset 589c3b3c92aSVijay Khemka */ 590c3b3c92aSVijay Khemka objectPath = "/xyz/openbmc_project/state/chassis0"; 591c3b3c92aSVijay Khemka } 592dd99e04bSP.K. Lee 593dd99e04bSP.K. Lee crow::connections::systemBus->async_method_call( 594dd99e04bSP.K. Lee [asyncResp](const boost::system::error_code ec) { 595dd99e04bSP.K. Lee // Use "Set" method to set the property value. 596dd99e04bSP.K. Lee if (ec) 597dd99e04bSP.K. Lee { 598c3b3c92aSVijay Khemka BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: " 599c3b3c92aSVijay Khemka << ec; 600dd99e04bSP.K. Lee messages::internalError(asyncResp->res); 601dd99e04bSP.K. Lee return; 602dd99e04bSP.K. Lee } 603dd99e04bSP.K. Lee 604dd99e04bSP.K. Lee messages::success(asyncResp->res); 605dd99e04bSP.K. Lee }, 606c3b3c92aSVijay Khemka processName, objectPath, "org.freedesktop.DBus.Properties", 607c3b3c92aSVijay Khemka "Set", interfaceName, destProperty, 608c3b3c92aSVijay Khemka std::variant<std::string>{propertyValue}); 609c3b3c92aSVijay Khemka }, 610c3b3c92aSVijay Khemka busName, path, interface, method, "/", 0, interfaces); 611dd99e04bSP.K. Lee } 612dd99e04bSP.K. Lee 613dd99e04bSP.K. Lee /** 614dd99e04bSP.K. Lee * ChassisResetAction class supports the POST method for the Reset 615dd99e04bSP.K. Lee * action. 616dd99e04bSP.K. Lee */ 617dd99e04bSP.K. Lee class ChassisResetAction : public Node 618dd99e04bSP.K. Lee { 619dd99e04bSP.K. Lee public: 62052cc112dSEd Tanous ChassisResetAction(App& app) : 621dd99e04bSP.K. Lee Node(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/", 622dd99e04bSP.K. Lee std::string()) 623dd99e04bSP.K. Lee { 624dd99e04bSP.K. Lee entityPrivileges = { 625dd99e04bSP.K. Lee {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 626dd99e04bSP.K. Lee } 627dd99e04bSP.K. Lee 628dd99e04bSP.K. Lee private: 629dd99e04bSP.K. Lee /** 630dd99e04bSP.K. Lee * Function handles POST method request. 631dd99e04bSP.K. Lee * Analyzes POST body before sending Reset request data to D-Bus. 632dd99e04bSP.K. Lee */ 633*8d1b46d7Szhanghch05 void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 634*8d1b46d7Szhanghch05 const crow::Request& req, 635cb13a392SEd Tanous const std::vector<std::string>&) override 636dd99e04bSP.K. Lee { 637dd99e04bSP.K. Lee BMCWEB_LOG_DEBUG << "Post Chassis Reset."; 638dd99e04bSP.K. Lee 639dd99e04bSP.K. Lee std::string resetType; 640dd99e04bSP.K. Lee 641dd99e04bSP.K. Lee if (!json_util::readJson(req, asyncResp->res, "ResetType", resetType)) 642dd99e04bSP.K. Lee { 643dd99e04bSP.K. Lee return; 644dd99e04bSP.K. Lee } 645dd99e04bSP.K. Lee 646dd99e04bSP.K. Lee if (resetType != "PowerCycle") 647dd99e04bSP.K. Lee { 648dd99e04bSP.K. Lee BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: " 649dd99e04bSP.K. Lee << resetType; 650dd99e04bSP.K. Lee messages::actionParameterNotSupported(asyncResp->res, resetType, 651dd99e04bSP.K. Lee "ResetType"); 652dd99e04bSP.K. Lee 653dd99e04bSP.K. Lee return; 654dd99e04bSP.K. Lee } 655dd99e04bSP.K. Lee doChassisPowerCycle(asyncResp); 656dd99e04bSP.K. Lee } 657dd99e04bSP.K. Lee }; 6581cb1a9e6SAppaRao Puli 6591cb1a9e6SAppaRao Puli /** 6601cb1a9e6SAppaRao Puli * ChassisResetActionInfo derived class for delivering Chassis 6611cb1a9e6SAppaRao Puli * ResetType AllowableValues using ResetInfo schema. 6621cb1a9e6SAppaRao Puli */ 6631cb1a9e6SAppaRao Puli class ChassisResetActionInfo : public Node 6641cb1a9e6SAppaRao Puli { 6651cb1a9e6SAppaRao Puli public: 6661cb1a9e6SAppaRao Puli /* 6671cb1a9e6SAppaRao Puli * Default Constructor 6681cb1a9e6SAppaRao Puli */ 66952cc112dSEd Tanous ChassisResetActionInfo(App& app) : 6701cb1a9e6SAppaRao Puli Node(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/", std::string()) 6711cb1a9e6SAppaRao Puli { 6721cb1a9e6SAppaRao Puli entityPrivileges = { 6731cb1a9e6SAppaRao Puli {boost::beast::http::verb::get, {{"Login"}}}, 6741cb1a9e6SAppaRao Puli {boost::beast::http::verb::head, {{"Login"}}}, 6751cb1a9e6SAppaRao Puli {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 6761cb1a9e6SAppaRao Puli {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 6771cb1a9e6SAppaRao Puli {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 6781cb1a9e6SAppaRao Puli {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 6791cb1a9e6SAppaRao Puli } 6801cb1a9e6SAppaRao Puli 6811cb1a9e6SAppaRao Puli private: 6821cb1a9e6SAppaRao Puli /** 6831cb1a9e6SAppaRao Puli * Functions triggers appropriate requests on DBus 6841cb1a9e6SAppaRao Puli */ 685*8d1b46d7Szhanghch05 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 686*8d1b46d7Szhanghch05 const crow::Request&, 6871cb1a9e6SAppaRao Puli const std::vector<std::string>& params) override 6881cb1a9e6SAppaRao Puli { 6891cb1a9e6SAppaRao Puli if (params.size() != 1) 6901cb1a9e6SAppaRao Puli { 691*8d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 6921cb1a9e6SAppaRao Puli return; 6931cb1a9e6SAppaRao Puli } 6941cb1a9e6SAppaRao Puli const std::string& chassisId = params[0]; 6951cb1a9e6SAppaRao Puli 696*8d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 697*8d1b46d7Szhanghch05 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"}, 698*8d1b46d7Szhanghch05 {"@odata.id", 699*8d1b46d7Szhanghch05 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"}, 7001cb1a9e6SAppaRao Puli {"Name", "Reset Action Info"}, 7011cb1a9e6SAppaRao Puli {"Id", "ResetActionInfo"}, 7021cb1a9e6SAppaRao Puli {"Parameters", 7031cb1a9e6SAppaRao Puli {{{"Name", "ResetType"}, 7041cb1a9e6SAppaRao Puli {"Required", true}, 7051cb1a9e6SAppaRao Puli {"DataType", "String"}, 7061cb1a9e6SAppaRao Puli {"AllowableValues", {"PowerCycle"}}}}}}; 7071cb1a9e6SAppaRao Puli } 7081cb1a9e6SAppaRao Puli }; 7091cb1a9e6SAppaRao Puli 710e37f8451SRapkiewicz, Pawel } // namespace redfish 711