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" 19*1c8fba97SJames Feist #include "led.hpp" 20e37f8451SRapkiewicz, Pawel #include "node.hpp" 211abe55efSEd Tanous 22e37f8451SRapkiewicz, Pawel #include <boost/container/flat_map.hpp> 23abf2add6SEd Tanous #include <variant> 24e37f8451SRapkiewicz, Pawel 251abe55efSEd Tanous namespace redfish 261abe55efSEd Tanous { 27e37f8451SRapkiewicz, Pawel 28e37f8451SRapkiewicz, Pawel /** 29beeca0aeSGunnar Mills * @brief Retrieves chassis state properties over dbus 30beeca0aeSGunnar Mills * 31beeca0aeSGunnar Mills * @param[in] aResp - Shared pointer for completing asynchronous calls. 32beeca0aeSGunnar Mills * 33beeca0aeSGunnar Mills * @return None. 34beeca0aeSGunnar Mills */ 35beeca0aeSGunnar Mills void getChassisState(std::shared_ptr<AsyncResp> aResp) 36beeca0aeSGunnar Mills { 37beeca0aeSGunnar Mills crow::connections::systemBus->async_method_call( 38beeca0aeSGunnar Mills [aResp{std::move(aResp)}]( 39beeca0aeSGunnar Mills const boost::system::error_code ec, 40beeca0aeSGunnar Mills const std::variant<std::string> &chassisState) { 41beeca0aeSGunnar Mills if (ec) 42beeca0aeSGunnar Mills { 43beeca0aeSGunnar Mills BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 44beeca0aeSGunnar Mills messages::internalError(aResp->res); 45beeca0aeSGunnar Mills return; 46beeca0aeSGunnar Mills } 47beeca0aeSGunnar Mills 48beeca0aeSGunnar Mills const std::string *s = std::get_if<std::string>(&chassisState); 49beeca0aeSGunnar Mills BMCWEB_LOG_DEBUG << "Chassis state: " << *s; 50beeca0aeSGunnar Mills if (s != nullptr) 51beeca0aeSGunnar Mills { 52beeca0aeSGunnar Mills // Verify Chassis State 53beeca0aeSGunnar Mills if (*s == "xyz.openbmc_project.State.Chassis.PowerState.On") 54beeca0aeSGunnar Mills { 55beeca0aeSGunnar Mills aResp->res.jsonValue["PowerState"] = "On"; 56beeca0aeSGunnar Mills aResp->res.jsonValue["Status"]["State"] = "Enabled"; 57beeca0aeSGunnar Mills } 58beeca0aeSGunnar Mills else if (*s == 59beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis.PowerState.Off") 60beeca0aeSGunnar Mills { 61beeca0aeSGunnar Mills aResp->res.jsonValue["PowerState"] = "Off"; 62beeca0aeSGunnar Mills aResp->res.jsonValue["Status"]["State"] = "StandbyOffline"; 63beeca0aeSGunnar Mills } 64beeca0aeSGunnar Mills } 65beeca0aeSGunnar Mills }, 66beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis", 67beeca0aeSGunnar Mills "/xyz/openbmc_project/state/chassis0", 68beeca0aeSGunnar Mills "org.freedesktop.DBus.Properties", "Get", 69beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis", "CurrentPowerState"); 70beeca0aeSGunnar Mills } 71beeca0aeSGunnar Mills 72beeca0aeSGunnar Mills /** 73e37f8451SRapkiewicz, Pawel * DBus types primitives for several generic DBus interfaces 74e37f8451SRapkiewicz, Pawel * TODO(Pawel) consider move this to separate file into boost::dbus 75e37f8451SRapkiewicz, Pawel */ 7655c7b7a2SEd Tanous // Note, this is not a very useful Variant, but because it isn't used to get 77aa2e59c1SEd Tanous // values, it should be as simple as possible 78aa2e59c1SEd Tanous // TODO(ed) invent a nullvariant type 795fd7ba65SCheng C Yang using VariantType = std::variant<bool, std::string, uint64_t, uint32_t>; 80aa2e59c1SEd Tanous using ManagedObjectsType = std::vector<std::pair< 81aa2e59c1SEd Tanous sdbusplus::message::object_path, 82aa2e59c1SEd Tanous std::vector<std::pair<std::string, 83aa2e59c1SEd Tanous std::vector<std::pair<std::string, VariantType>>>>>>; 84e37f8451SRapkiewicz, Pawel 85aa2e59c1SEd Tanous using PropertiesType = boost::container::flat_map<std::string, VariantType>; 86e37f8451SRapkiewicz, Pawel 87c181942fSQiang XU void getIntrusionByService(std::shared_ptr<AsyncResp> aResp, 88c181942fSQiang XU const std::string &service, 89c181942fSQiang XU const std::string &objPath) 90c181942fSQiang XU { 91c181942fSQiang XU BMCWEB_LOG_DEBUG << "Get intrusion status by service \n"; 92c181942fSQiang XU 93c181942fSQiang XU crow::connections::systemBus->async_method_call( 94c181942fSQiang XU [aResp{std::move(aResp)}](const boost::system::error_code ec, 95c181942fSQiang XU const std::variant<std::string> &value) { 96c181942fSQiang XU if (ec) 97c181942fSQiang XU { 98c181942fSQiang XU // do not add err msg in redfish response, becaues this is not 99c181942fSQiang XU // mandatory property 100c181942fSQiang XU BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n"; 101c181942fSQiang XU return; 102c181942fSQiang XU } 103c181942fSQiang XU 104c181942fSQiang XU const std::string *status = std::get_if<std::string>(&value); 105c181942fSQiang XU 106c181942fSQiang XU if (status == nullptr) 107c181942fSQiang XU { 108c181942fSQiang XU BMCWEB_LOG_ERROR << "intrusion status read error \n"; 109c181942fSQiang XU return; 110c181942fSQiang XU } 111c181942fSQiang XU 112c181942fSQiang XU aResp->res.jsonValue["PhysicalSecurity"] = { 113c181942fSQiang XU {"IntrusionSensorNumber", 1}, {"IntrusionSensor", *status}}; 114c181942fSQiang XU }, 115c181942fSQiang XU service, objPath, "org.freedesktop.DBus.Properties", "Get", 116c181942fSQiang XU "xyz.openbmc_project.Chassis.Intrusion", "Status"); 117c181942fSQiang XU } 118c181942fSQiang XU 119c181942fSQiang XU /** 120c181942fSQiang XU * Retrieves physical security properties over dbus 121c181942fSQiang XU */ 122c181942fSQiang XU void getPhysicalSecurityData(std::shared_ptr<AsyncResp> aResp) 123c181942fSQiang XU { 124c181942fSQiang XU crow::connections::systemBus->async_method_call( 125c181942fSQiang XU [aResp{std::move(aResp)}]( 126c181942fSQiang XU const boost::system::error_code ec, 127c181942fSQiang XU const std::vector<std::pair< 128c181942fSQiang XU std::string, 129c181942fSQiang XU std::vector<std::pair<std::string, std::vector<std::string>>>>> 130c181942fSQiang XU &subtree) { 131c181942fSQiang XU if (ec) 132c181942fSQiang XU { 133c181942fSQiang XU // do not add err msg in redfish response, becaues this is not 134c181942fSQiang XU // mandatory property 135c181942fSQiang XU BMCWEB_LOG_ERROR << "DBUS error: no matched iface " << ec 136c181942fSQiang XU << "\n"; 137c181942fSQiang XU return; 138c181942fSQiang XU } 139c181942fSQiang XU // Iterate over all retrieved ObjectPaths. 140c181942fSQiang XU for (const auto &object : subtree) 141c181942fSQiang XU { 142c181942fSQiang XU for (const auto &service : object.second) 143c181942fSQiang XU { 144c181942fSQiang XU getIntrusionByService(aResp, service.first, object.first); 145c181942fSQiang XU return; 146c181942fSQiang XU } 147c181942fSQiang XU } 148c181942fSQiang XU }, 149c181942fSQiang XU "xyz.openbmc_project.ObjectMapper", 150c181942fSQiang XU "/xyz/openbmc_project/object_mapper", 151c181942fSQiang XU "xyz.openbmc_project.ObjectMapper", "GetSubTree", 152271584abSEd Tanous "/xyz/openbmc_project/Intrusion", 1, 153c181942fSQiang XU std::array<const char *, 1>{"xyz.openbmc_project.Chassis.Intrusion"}); 154c181942fSQiang XU } 155c181942fSQiang XU 156e37f8451SRapkiewicz, Pawel /** 157e37f8451SRapkiewicz, Pawel * ChassisCollection derived class for delivering Chassis Collection Schema 158e37f8451SRapkiewicz, Pawel */ 1591abe55efSEd Tanous class ChassisCollection : public Node 1601abe55efSEd Tanous { 161e37f8451SRapkiewicz, Pawel public: 1621abe55efSEd Tanous ChassisCollection(CrowApp &app) : Node(app, "/redfish/v1/Chassis/") 1631abe55efSEd Tanous { 164e0d918bcSEd Tanous entityPrivileges = { 165e0d918bcSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 166e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 167e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 168e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 169e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 170e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 171e37f8451SRapkiewicz, Pawel } 172e37f8451SRapkiewicz, Pawel 173e37f8451SRapkiewicz, Pawel private: 174e37f8451SRapkiewicz, Pawel /** 175e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 176e37f8451SRapkiewicz, Pawel */ 17755c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 1781abe55efSEd Tanous const std::vector<std::string> ¶ms) override 1791abe55efSEd Tanous { 1800f74e643SEd Tanous res.jsonValue["@odata.type"] = "#ChassisCollection.ChassisCollection"; 1810f74e643SEd Tanous res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 1820f74e643SEd Tanous res.jsonValue["@odata.context"] = 1830f74e643SEd Tanous "/redfish/v1/$metadata#ChassisCollection.ChassisCollection"; 1840f74e643SEd Tanous res.jsonValue["Name"] = "Chassis Collection"; 1850f74e643SEd Tanous 186adc4f0dbSShawn McCarney const std::array<const char *, 2> interfaces = { 187603a6640SGunnar Mills "xyz.openbmc_project.Inventory.Item.Board", 188adc4f0dbSShawn McCarney "xyz.openbmc_project.Inventory.Item.Chassis"}; 189603a6640SGunnar Mills 19062d5e2e4SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 19162d5e2e4SEd Tanous crow::connections::systemBus->async_method_call( 19262d5e2e4SEd Tanous [asyncResp](const boost::system::error_code ec, 19362d5e2e4SEd Tanous const std::vector<std::string> &chassisList) { 19462d5e2e4SEd Tanous if (ec) 1951abe55efSEd Tanous { 196f12894f8SJason M. Bills messages::internalError(asyncResp->res); 19762d5e2e4SEd Tanous return; 198e37f8451SRapkiewicz, Pawel } 19962d5e2e4SEd Tanous nlohmann::json &chassisArray = 20062d5e2e4SEd Tanous asyncResp->res.jsonValue["Members"]; 20162d5e2e4SEd Tanous chassisArray = nlohmann::json::array(); 20262d5e2e4SEd Tanous for (const std::string &objpath : chassisList) 20362d5e2e4SEd Tanous { 20462d5e2e4SEd Tanous std::size_t lastPos = objpath.rfind("/"); 20562d5e2e4SEd Tanous if (lastPos == std::string::npos) 20662d5e2e4SEd Tanous { 20762d5e2e4SEd Tanous BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath; 20862d5e2e4SEd Tanous continue; 20962d5e2e4SEd Tanous } 21062d5e2e4SEd Tanous chassisArray.push_back( 21162d5e2e4SEd Tanous {{"@odata.id", "/redfish/v1/Chassis/" + 21262d5e2e4SEd Tanous objpath.substr(lastPos + 1)}}); 213e37f8451SRapkiewicz, Pawel } 214e37f8451SRapkiewicz, Pawel 21562d5e2e4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 21662d5e2e4SEd Tanous chassisArray.size(); 21762d5e2e4SEd Tanous }, 21862d5e2e4SEd Tanous "xyz.openbmc_project.ObjectMapper", 21962d5e2e4SEd Tanous "/xyz/openbmc_project/object_mapper", 22062d5e2e4SEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 221271584abSEd Tanous "/xyz/openbmc_project/inventory", 0, interfaces); 22262d5e2e4SEd Tanous } 223e37f8451SRapkiewicz, Pawel }; 224e37f8451SRapkiewicz, Pawel 225e37f8451SRapkiewicz, Pawel /** 226e37f8451SRapkiewicz, Pawel * Chassis override class for delivering Chassis Schema 227e37f8451SRapkiewicz, Pawel */ 2281abe55efSEd Tanous class Chassis : public Node 2291abe55efSEd Tanous { 230e37f8451SRapkiewicz, Pawel public: 2311abe55efSEd Tanous Chassis(CrowApp &app) : 2321abe55efSEd Tanous Node(app, "/redfish/v1/Chassis/<str>/", std::string()) 2331abe55efSEd Tanous { 234e0d918bcSEd Tanous entityPrivileges = { 235e0d918bcSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 236e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 237e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 238e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 239e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 240e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 241e37f8451SRapkiewicz, Pawel } 242e37f8451SRapkiewicz, Pawel 243e37f8451SRapkiewicz, Pawel private: 244e37f8451SRapkiewicz, Pawel /** 245e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 246e37f8451SRapkiewicz, Pawel */ 24755c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 2481abe55efSEd Tanous const std::vector<std::string> ¶ms) override 2491abe55efSEd Tanous { 250adc4f0dbSShawn McCarney const std::array<const char *, 2> interfaces = { 251734bfe90SGunnar Mills "xyz.openbmc_project.Inventory.Item.Board", 252adc4f0dbSShawn McCarney "xyz.openbmc_project.Inventory.Item.Chassis"}; 253734bfe90SGunnar Mills 254e37f8451SRapkiewicz, Pawel // Check if there is required param, truly entering this shall be 255e37f8451SRapkiewicz, Pawel // impossible. 2561abe55efSEd Tanous if (params.size() != 1) 2571abe55efSEd Tanous { 258f12894f8SJason M. Bills messages::internalError(res); 259e37f8451SRapkiewicz, Pawel res.end(); 260e37f8451SRapkiewicz, Pawel return; 261e37f8451SRapkiewicz, Pawel } 26299cffd7fSShawn McCarney const std::string &chassisId = params[0]; 263e37f8451SRapkiewicz, Pawel 26462d5e2e4SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 26555c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 26662d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 26762d5e2e4SEd Tanous const boost::system::error_code ec, 268*1c8fba97SJames Feist const crow::openbmc_mapper::GetSubTreeType &subtree) { 26962d5e2e4SEd Tanous if (ec) 2701abe55efSEd Tanous { 271f12894f8SJason M. Bills messages::internalError(asyncResp->res); 272daf36e2eSEd Tanous return; 273daf36e2eSEd Tanous } 274daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 2751abe55efSEd Tanous for (const std::pair< 2761abe55efSEd Tanous std::string, 2771abe55efSEd Tanous std::vector< 2781abe55efSEd Tanous std::pair<std::string, std::vector<std::string>>>> 2791abe55efSEd Tanous &object : subtree) 2801abe55efSEd Tanous { 281daf36e2eSEd Tanous const std::string &path = object.first; 2821abe55efSEd Tanous const std::vector< 2831abe55efSEd Tanous std::pair<std::string, std::vector<std::string>>> 284daf36e2eSEd Tanous &connectionNames = object.second; 285e0d918bcSEd Tanous 2861abe55efSEd Tanous if (!boost::ends_with(path, chassisId)) 2871abe55efSEd Tanous { 288daf36e2eSEd Tanous continue; 289daf36e2eSEd Tanous } 29026f03899SShawn McCarney 291b49ac873SJames Feist auto health = std::make_shared<HealthPopulate>(asyncResp); 292b49ac873SJames Feist 293b49ac873SJames Feist crow::connections::systemBus->async_method_call( 294b49ac873SJames Feist [health](const boost::system::error_code ec, 295b49ac873SJames Feist std::variant<std::vector<std::string>> &resp) { 296b49ac873SJames Feist if (ec) 297b49ac873SJames Feist { 298b49ac873SJames Feist return; // no sensors = no failures 299b49ac873SJames Feist } 300b49ac873SJames Feist std::vector<std::string> *data = 301b49ac873SJames Feist std::get_if<std::vector<std::string>>(&resp); 302b49ac873SJames Feist if (data == nullptr) 303b49ac873SJames Feist { 304b49ac873SJames Feist return; 305b49ac873SJames Feist } 306b49ac873SJames Feist health->inventory = std::move(*data); 307b49ac873SJames Feist }, 308b49ac873SJames Feist "xyz.openbmc_project.ObjectMapper", 309b49ac873SJames Feist path + "/all_sensors", 310b49ac873SJames Feist "org.freedesktop.DBus.Properties", "Get", 311b49ac873SJames Feist "xyz.openbmc_project.Association", "endpoints"); 312b49ac873SJames Feist 313b49ac873SJames Feist health->populate(); 314b49ac873SJames Feist 3151abe55efSEd Tanous if (connectionNames.size() < 1) 3161abe55efSEd Tanous { 317*1c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 318e0d918bcSEd Tanous continue; 319daf36e2eSEd Tanous } 320e0d918bcSEd Tanous 32149c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.type"] = 322adbe192aSJason M. Bills "#Chassis.v1_10_0.Chassis"; 32349c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.id"] = 32449c53ac9SJohnathan Mantey "/redfish/v1/Chassis/" + chassisId; 32549c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.context"] = 32649c53ac9SJohnathan Mantey "/redfish/v1/$metadata#Chassis.Chassis"; 32749c53ac9SJohnathan Mantey asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 32849c53ac9SJohnathan Mantey asyncResp->res.jsonValue["ChassisType"] = "RackMount"; 329adbe192aSJason M. Bills asyncResp->res.jsonValue["PCIeDevices"] = { 330adbe192aSJason M. Bills {"@odata.id", 331adbe192aSJason M. Bills "/redfish/v1/Systems/system/PCIeDevices"}}; 33249c53ac9SJohnathan Mantey 33349c53ac9SJohnathan Mantey const std::string &connectionName = 33449c53ac9SJohnathan Mantey connectionNames[0].first; 335*1c8fba97SJames Feist 336*1c8fba97SJames Feist const std::vector<std::string> &interfaces = 337*1c8fba97SJames Feist connectionNames[0].second; 338*1c8fba97SJames Feist const std::array<const char *, 2> hasIndicatorLed = { 339*1c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 340*1c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 341*1c8fba97SJames Feist 342*1c8fba97SJames Feist for (const char *interface : hasIndicatorLed) 343*1c8fba97SJames Feist { 344*1c8fba97SJames Feist if (std::find(interfaces.begin(), interfaces.end(), 345*1c8fba97SJames Feist interface) != interfaces.end()) 346*1c8fba97SJames Feist { 347*1c8fba97SJames Feist getIndicatorLedState(asyncResp); 348*1c8fba97SJames Feist break; 349*1c8fba97SJames Feist } 350*1c8fba97SJames Feist } 351*1c8fba97SJames Feist 35255c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 35362d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 35462d5e2e4SEd Tanous const boost::system::error_code ec, 3551abe55efSEd Tanous const std::vector<std::pair< 3561abe55efSEd Tanous std::string, VariantType>> &propertiesList) { 3571abe55efSEd Tanous for (const std::pair<std::string, VariantType> 3581abe55efSEd Tanous &property : propertiesList) 3591abe55efSEd Tanous { 36099cffd7fSShawn McCarney // Store DBus properties that are also Redfish 36199cffd7fSShawn McCarney // properties with same name and a string value 36299cffd7fSShawn McCarney const std::string &propertyName = 36399cffd7fSShawn McCarney property.first; 36499cffd7fSShawn McCarney if ((propertyName == "PartNumber") || 36599cffd7fSShawn McCarney (propertyName == "SerialNumber") || 36699cffd7fSShawn McCarney (propertyName == "Manufacturer") || 36799cffd7fSShawn McCarney (propertyName == "Model")) 36899cffd7fSShawn McCarney { 369daf36e2eSEd Tanous const std::string *value = 37099cffd7fSShawn McCarney std::get_if<std::string>( 37199cffd7fSShawn McCarney &property.second); 3721abe55efSEd Tanous if (value != nullptr) 3731abe55efSEd Tanous { 37499cffd7fSShawn McCarney asyncResp->res.jsonValue[propertyName] = 37562d5e2e4SEd Tanous *value; 376daf36e2eSEd Tanous } 377daf36e2eSEd Tanous } 37899cffd7fSShawn McCarney } 37962d5e2e4SEd Tanous asyncResp->res.jsonValue["Name"] = chassisId; 38062d5e2e4SEd Tanous asyncResp->res.jsonValue["Id"] = chassisId; 38162d5e2e4SEd Tanous asyncResp->res.jsonValue["Thermal"] = { 3821abe55efSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 3831abe55efSEd Tanous chassisId + "/Thermal"}}; 3842474adfaSEd Tanous // Power object 3852474adfaSEd Tanous asyncResp->res.jsonValue["Power"] = { 3862474adfaSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 3872474adfaSEd Tanous chassisId + "/Power"}}; 38895a3ecadSAnthony Wilson // SensorCollection 38995a3ecadSAnthony Wilson asyncResp->res.jsonValue["Sensors"] = { 39095a3ecadSAnthony Wilson {"@odata.id", "/redfish/v1/Chassis/" + 39195a3ecadSAnthony Wilson chassisId + "/Sensors"}}; 392029573d4SEd Tanous asyncResp->res.jsonValue["Status"] = { 393029573d4SEd Tanous {"State", "Enabled"}, 394029573d4SEd Tanous }; 3952474adfaSEd Tanous 396029573d4SEd Tanous asyncResp->res 397029573d4SEd Tanous .jsonValue["Links"]["ComputerSystems"] = { 398029573d4SEd Tanous {{"@odata.id", "/redfish/v1/Systems/system"}}}; 399029573d4SEd Tanous asyncResp->res.jsonValue["Links"]["ManagedBy"] = { 400029573d4SEd Tanous {{"@odata.id", "/redfish/v1/Managers/bmc"}}}; 401beeca0aeSGunnar Mills getChassisState(asyncResp); 402daf36e2eSEd Tanous }, 403daf36e2eSEd Tanous connectionName, path, "org.freedesktop.DBus.Properties", 4041abe55efSEd Tanous "GetAll", 4051abe55efSEd Tanous "xyz.openbmc_project.Inventory.Decorator.Asset"); 406daf36e2eSEd Tanous return; 407daf36e2eSEd Tanous } 408e0d918bcSEd Tanous 409daf36e2eSEd Tanous // Couldn't find an object with that name. return an error 410f12894f8SJason M. Bills messages::resourceNotFound( 411adbe192aSJason M. Bills asyncResp->res, "#Chassis.v1_10_0.Chassis", chassisId); 412daf36e2eSEd Tanous }, 413daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", 414daf36e2eSEd Tanous "/xyz/openbmc_project/object_mapper", 415daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTree", 416271584abSEd Tanous "/xyz/openbmc_project/inventory", 0, interfaces); 417c181942fSQiang XU 418c181942fSQiang XU getPhysicalSecurityData(asyncResp); 419e37f8451SRapkiewicz, Pawel } 420*1c8fba97SJames Feist 421*1c8fba97SJames Feist void doPatch(crow::Response &res, const crow::Request &req, 422*1c8fba97SJames Feist const std::vector<std::string> ¶ms) override 423*1c8fba97SJames Feist { 424*1c8fba97SJames Feist std::optional<std::string> indicatorLed; 425*1c8fba97SJames Feist auto asyncResp = std::make_shared<AsyncResp>(res); 426*1c8fba97SJames Feist 427*1c8fba97SJames Feist if (params.size() != 1) 428*1c8fba97SJames Feist { 429*1c8fba97SJames Feist return; 430*1c8fba97SJames Feist } 431*1c8fba97SJames Feist 432*1c8fba97SJames Feist if (!json_util::readJson(req, res, "IndicatorLED", indicatorLed)) 433*1c8fba97SJames Feist { 434*1c8fba97SJames Feist return; 435*1c8fba97SJames Feist } 436*1c8fba97SJames Feist 437*1c8fba97SJames Feist if (!indicatorLed) 438*1c8fba97SJames Feist { 439*1c8fba97SJames Feist return; // delete this when we support more patch properties 440*1c8fba97SJames Feist } 441*1c8fba97SJames Feist 442*1c8fba97SJames Feist const std::array<const char *, 2> interfaces = { 443*1c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board", 444*1c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Chassis"}; 445*1c8fba97SJames Feist 446*1c8fba97SJames Feist const std::string &chassisId = params[0]; 447*1c8fba97SJames Feist 448*1c8fba97SJames Feist crow::connections::systemBus->async_method_call( 449*1c8fba97SJames Feist [asyncResp, chassisId, indicatorLed]( 450*1c8fba97SJames Feist const boost::system::error_code ec, 451*1c8fba97SJames Feist const crow::openbmc_mapper::GetSubTreeType &subtree) { 452*1c8fba97SJames Feist if (ec) 453*1c8fba97SJames Feist { 454*1c8fba97SJames Feist messages::internalError(asyncResp->res); 455*1c8fba97SJames Feist return; 456*1c8fba97SJames Feist } 457*1c8fba97SJames Feist 458*1c8fba97SJames Feist // Iterate over all retrieved ObjectPaths. 459*1c8fba97SJames Feist for (const std::pair< 460*1c8fba97SJames Feist std::string, 461*1c8fba97SJames Feist std::vector< 462*1c8fba97SJames Feist std::pair<std::string, std::vector<std::string>>>> 463*1c8fba97SJames Feist &object : subtree) 464*1c8fba97SJames Feist { 465*1c8fba97SJames Feist const std::string &path = object.first; 466*1c8fba97SJames Feist const std::vector< 467*1c8fba97SJames Feist std::pair<std::string, std::vector<std::string>>> 468*1c8fba97SJames Feist &connectionNames = object.second; 469*1c8fba97SJames Feist 470*1c8fba97SJames Feist if (!boost::ends_with(path, chassisId)) 471*1c8fba97SJames Feist { 472*1c8fba97SJames Feist continue; 473*1c8fba97SJames Feist } 474*1c8fba97SJames Feist 475*1c8fba97SJames Feist if (connectionNames.size() < 1) 476*1c8fba97SJames Feist { 477*1c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 478*1c8fba97SJames Feist continue; 479*1c8fba97SJames Feist } 480*1c8fba97SJames Feist 481*1c8fba97SJames Feist const std::vector<std::string> &interfaces = 482*1c8fba97SJames Feist connectionNames[0].second; 483*1c8fba97SJames Feist 484*1c8fba97SJames Feist if (indicatorLed) 485*1c8fba97SJames Feist { 486*1c8fba97SJames Feist const std::array<const char *, 2> hasIndicatorLed = { 487*1c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 488*1c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board." 489*1c8fba97SJames Feist "Motherboard"}; 490*1c8fba97SJames Feist bool indicatorChassis = false; 491*1c8fba97SJames Feist for (const char *interface : hasIndicatorLed) 492*1c8fba97SJames Feist { 493*1c8fba97SJames Feist if (std::find(interfaces.begin(), interfaces.end(), 494*1c8fba97SJames Feist interface) != interfaces.end()) 495*1c8fba97SJames Feist { 496*1c8fba97SJames Feist indicatorChassis = true; 497*1c8fba97SJames Feist break; 498*1c8fba97SJames Feist } 499*1c8fba97SJames Feist } 500*1c8fba97SJames Feist if (indicatorChassis) 501*1c8fba97SJames Feist { 502*1c8fba97SJames Feist setIndicatorLedState(asyncResp, 503*1c8fba97SJames Feist std::move(*indicatorLed)); 504*1c8fba97SJames Feist } 505*1c8fba97SJames Feist else 506*1c8fba97SJames Feist { 507*1c8fba97SJames Feist messages::propertyUnknown(asyncResp->res, 508*1c8fba97SJames Feist "IndicatorLED"); 509*1c8fba97SJames Feist } 510*1c8fba97SJames Feist } 511*1c8fba97SJames Feist return; 512*1c8fba97SJames Feist } 513*1c8fba97SJames Feist 514*1c8fba97SJames Feist messages::resourceNotFound( 515*1c8fba97SJames Feist asyncResp->res, "#Chassis.v1_10_0.Chassis", chassisId); 516*1c8fba97SJames Feist }, 517*1c8fba97SJames Feist "xyz.openbmc_project.ObjectMapper", 518*1c8fba97SJames Feist "/xyz/openbmc_project/object_mapper", 519*1c8fba97SJames Feist "xyz.openbmc_project.ObjectMapper", "GetSubTree", 520*1c8fba97SJames Feist "/xyz/openbmc_project/inventory", 0, interfaces); 521*1c8fba97SJames Feist } 52262d5e2e4SEd Tanous }; 523e37f8451SRapkiewicz, Pawel } // namespace redfish 524