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> 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 */ 378d1b46d7Szhanghch05 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 898d1b46d7Szhanghch05 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 */ 1248d1b46d7Szhanghch05 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 * Functions triggers appropriate requests on DBus 161e37f8451SRapkiewicz, Pawel */ 1627e860f15SJohn Edward Broadbent inline void requestRoutesChassisCollection(App& app) 1631abe55efSEd Tanous { 1647e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/") 1657e860f15SJohn Edward Broadbent .privileges({"Login"}) 1667e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 1677e860f15SJohn Edward Broadbent [](const crow::Request&, 1687e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1698d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1708d1b46d7Szhanghch05 "#ChassisCollection.ChassisCollection"; 1718d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 1728d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 173e37f8451SRapkiewicz, Pawel 17402f6ff19SGunnar Mills collection_util::getCollectionMembers( 17502f6ff19SGunnar Mills asyncResp, "/redfish/v1/Chassis", 17602f6ff19SGunnar Mills {"xyz.openbmc_project.Inventory.Item.Board", 17702f6ff19SGunnar Mills "xyz.openbmc_project.Inventory.Item.Chassis"}); 1787e860f15SJohn Edward Broadbent }); 17962d5e2e4SEd Tanous } 180e37f8451SRapkiewicz, Pawel 181e37f8451SRapkiewicz, Pawel /** 182e37f8451SRapkiewicz, Pawel * Chassis override class for delivering Chassis Schema 183e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 184e37f8451SRapkiewicz, Pawel */ 1857e860f15SJohn Edward Broadbent inline void requestRoutesChassis(App& app) 1861abe55efSEd Tanous { 1877e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 1887e860f15SJohn Edward Broadbent .privileges({"Login"}) 1897e860f15SJohn Edward Broadbent .methods( 1907e860f15SJohn Edward Broadbent boost::beast::http::verb::get)([](const crow::Request&, 1917e860f15SJohn Edward Broadbent const std::shared_ptr< 1927e860f15SJohn Edward Broadbent bmcweb::AsyncResp>& asyncResp, 1937e860f15SJohn Edward Broadbent const std::string& chassisId) { 194adc4f0dbSShawn McCarney const std::array<const char*, 2> interfaces = { 195734bfe90SGunnar Mills "xyz.openbmc_project.Inventory.Item.Board", 196adc4f0dbSShawn McCarney "xyz.openbmc_project.Inventory.Item.Chassis"}; 197734bfe90SGunnar Mills 19855c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 19962d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 20062d5e2e4SEd Tanous const boost::system::error_code ec, 2011c8fba97SJames Feist const crow::openbmc_mapper::GetSubTreeType& subtree) { 20262d5e2e4SEd Tanous if (ec) 2031abe55efSEd Tanous { 204f12894f8SJason M. Bills messages::internalError(asyncResp->res); 205daf36e2eSEd Tanous return; 206daf36e2eSEd Tanous } 207daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 2081abe55efSEd Tanous for (const std::pair< 2091abe55efSEd Tanous std::string, 2107e860f15SJohn Edward Broadbent std::vector<std::pair<std::string, 2117e860f15SJohn Edward Broadbent std::vector<std::string>>>>& 2121214b7e7SGunnar Mills object : subtree) 2131abe55efSEd Tanous { 214daf36e2eSEd Tanous const std::string& path = object.first; 2151abe55efSEd Tanous const std::vector< 2161214b7e7SGunnar Mills std::pair<std::string, std::vector<std::string>>>& 2171214b7e7SGunnar Mills connectionNames = object.second; 2187e860f15SJohn Edward Broadbent 2197e860f15SJohn Edward Broadbent if (!boost::ends_with(path, chassisId)) 2201abe55efSEd Tanous { 221daf36e2eSEd Tanous continue; 222daf36e2eSEd Tanous } 22326f03899SShawn McCarney 2247e860f15SJohn Edward Broadbent auto health = 2257e860f15SJohn Edward Broadbent std::make_shared<HealthPopulate>(asyncResp); 226b49ac873SJames Feist 227b49ac873SJames Feist crow::connections::systemBus->async_method_call( 2287e860f15SJohn Edward Broadbent [health]( 2297e860f15SJohn Edward Broadbent const boost::system::error_code ec2, 230b49ac873SJames Feist std::variant<std::vector<std::string>>& resp) { 23123a21a1cSEd Tanous if (ec2) 232b49ac873SJames Feist { 233b49ac873SJames Feist return; // no sensors = no failures 234b49ac873SJames Feist } 235b49ac873SJames Feist std::vector<std::string>* data = 2367e860f15SJohn Edward Broadbent std::get_if<std::vector<std::string>>( 2377e860f15SJohn Edward Broadbent &resp); 238b49ac873SJames Feist if (data == nullptr) 239b49ac873SJames Feist { 240b49ac873SJames Feist return; 241b49ac873SJames Feist } 242b49ac873SJames Feist health->inventory = std::move(*data); 243b49ac873SJames Feist }, 244b49ac873SJames Feist "xyz.openbmc_project.ObjectMapper", 245b49ac873SJames Feist path + "/all_sensors", 246b49ac873SJames Feist "org.freedesktop.DBus.Properties", "Get", 247b49ac873SJames Feist "xyz.openbmc_project.Association", "endpoints"); 248b49ac873SJames Feist 249b49ac873SJames Feist health->populate(); 250b49ac873SJames Feist 2511abe55efSEd Tanous if (connectionNames.size() < 1) 2521abe55efSEd Tanous { 2531c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 254e0d918bcSEd Tanous continue; 255daf36e2eSEd Tanous } 256e0d918bcSEd Tanous 25749c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.type"] = 2589f8bfa7cSGunnar Mills "#Chassis.v1_14_0.Chassis"; 25949c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.id"] = 26049c53ac9SJohnathan Mantey "/redfish/v1/Chassis/" + chassisId; 26149c53ac9SJohnathan Mantey asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 26249c53ac9SJohnathan Mantey asyncResp->res.jsonValue["ChassisType"] = "RackMount"; 2637e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] = 2647e860f15SJohn Edward Broadbent {{"target", "/redfish/v1/Chassis/" + chassisId + 265dd99e04bSP.K. Lee "/Actions/Chassis.Reset"}, 2661cb1a9e6SAppaRao Puli {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" + 2671cb1a9e6SAppaRao Puli chassisId + 2681cb1a9e6SAppaRao Puli "/ResetActionInfo"}}; 269adbe192aSJason M. Bills asyncResp->res.jsonValue["PCIeDevices"] = { 270adbe192aSJason M. Bills {"@odata.id", 271adbe192aSJason M. Bills "/redfish/v1/Systems/system/PCIeDevices"}}; 27249c53ac9SJohnathan Mantey 27349c53ac9SJohnathan Mantey const std::string& connectionName = 27449c53ac9SJohnathan Mantey connectionNames[0].first; 2751c8fba97SJames Feist 27623a21a1cSEd Tanous const std::vector<std::string>& interfaces2 = 2771c8fba97SJames Feist connectionNames[0].second; 2781c8fba97SJames Feist const std::array<const char*, 2> hasIndicatorLed = { 2791c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 2807e860f15SJohn Edward Broadbent "xyz.openbmc_project.Inventory.Item.Board." 2817e860f15SJohn Edward Broadbent "Motherboard"}; 2821c8fba97SJames Feist 2831c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 2841c8fba97SJames Feist { 2857e860f15SJohn Edward Broadbent if (std::find(interfaces2.begin(), 2867e860f15SJohn Edward Broadbent interfaces2.end(), 28723a21a1cSEd Tanous interface) != interfaces2.end()) 2881c8fba97SJames Feist { 2891c8fba97SJames Feist getIndicatorLedState(asyncResp); 2909f8bfa7cSGunnar Mills getLocationIndicatorActive(asyncResp); 2911c8fba97SJames Feist break; 2921c8fba97SJames Feist } 2931c8fba97SJames Feist } 2941c8fba97SJames Feist 29588ad7f03SSunnySrivastava1984 const std::string locationInterface = 2967e860f15SJohn Edward Broadbent "xyz.openbmc_project.Inventory.Decorator." 2977e860f15SJohn Edward Broadbent "LocationCode"; 29888ad7f03SSunnySrivastava1984 if (std::find(interfaces2.begin(), interfaces2.end(), 29988ad7f03SSunnySrivastava1984 locationInterface) != interfaces2.end()) 30088ad7f03SSunnySrivastava1984 { 30188ad7f03SSunnySrivastava1984 crow::connections::systemBus->async_method_call( 30288ad7f03SSunnySrivastava1984 [asyncResp, chassisId(std::string(chassisId))]( 30388ad7f03SSunnySrivastava1984 const boost::system::error_code ec, 30488ad7f03SSunnySrivastava1984 const std::variant<std::string>& property) { 30588ad7f03SSunnySrivastava1984 if (ec) 30688ad7f03SSunnySrivastava1984 { 30788ad7f03SSunnySrivastava1984 BMCWEB_LOG_DEBUG 3087e860f15SJohn Edward Broadbent << "DBUS response error for " 3097e860f15SJohn Edward Broadbent "Location"; 31088ad7f03SSunnySrivastava1984 messages::internalError(asyncResp->res); 31188ad7f03SSunnySrivastava1984 return; 31288ad7f03SSunnySrivastava1984 } 31388ad7f03SSunnySrivastava1984 31488ad7f03SSunnySrivastava1984 const std::string* value = 31588ad7f03SSunnySrivastava1984 std::get_if<std::string>(&property); 31688ad7f03SSunnySrivastava1984 if (value == nullptr) 31788ad7f03SSunnySrivastava1984 { 3187e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG 3197e860f15SJohn Edward Broadbent << "Null value returned " 32088ad7f03SSunnySrivastava1984 "for locaton code"; 32188ad7f03SSunnySrivastava1984 messages::internalError(asyncResp->res); 32288ad7f03SSunnySrivastava1984 return; 32388ad7f03SSunnySrivastava1984 } 32488ad7f03SSunnySrivastava1984 asyncResp->res 32588ad7f03SSunnySrivastava1984 .jsonValue["Location"]["PartLocation"] 32688ad7f03SSunnySrivastava1984 ["ServiceLabel"] = *value; 32788ad7f03SSunnySrivastava1984 }, 32888ad7f03SSunnySrivastava1984 connectionName, path, 32988ad7f03SSunnySrivastava1984 "org.freedesktop.DBus.Properties", "Get", 33088ad7f03SSunnySrivastava1984 locationInterface, "LocationCode"); 33188ad7f03SSunnySrivastava1984 } 33288ad7f03SSunnySrivastava1984 33355c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 33462d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 33590728b54SEd Tanous const boost::system::error_code /*ec2*/, 3367e860f15SJohn Edward Broadbent const std::vector< 3377e860f15SJohn Edward Broadbent std::pair<std::string, VariantType>>& 3387e860f15SJohn Edward Broadbent propertiesList) { 3391214b7e7SGunnar Mills for (const std::pair<std::string, VariantType>& 3401214b7e7SGunnar Mills property : propertiesList) 3411abe55efSEd Tanous { 3427e860f15SJohn Edward Broadbent // Store DBus properties that are also 3437e860f15SJohn Edward Broadbent // Redfish properties with same name and a 3447e860f15SJohn Edward Broadbent // string value 34599cffd7fSShawn McCarney const std::string& propertyName = 34699cffd7fSShawn McCarney property.first; 34799cffd7fSShawn McCarney if ((propertyName == "PartNumber") || 34899cffd7fSShawn McCarney (propertyName == "SerialNumber") || 34999cffd7fSShawn McCarney (propertyName == "Manufacturer") || 35099cffd7fSShawn McCarney (propertyName == "Model")) 35199cffd7fSShawn McCarney { 352daf36e2eSEd Tanous const std::string* value = 35399cffd7fSShawn McCarney std::get_if<std::string>( 35499cffd7fSShawn McCarney &property.second); 3551abe55efSEd Tanous if (value != nullptr) 3561abe55efSEd Tanous { 3577e860f15SJohn Edward Broadbent asyncResp->res 3587e860f15SJohn Edward Broadbent .jsonValue[propertyName] = 35962d5e2e4SEd Tanous *value; 360daf36e2eSEd Tanous } 361daf36e2eSEd Tanous } 36299cffd7fSShawn McCarney } 36362d5e2e4SEd Tanous asyncResp->res.jsonValue["Name"] = chassisId; 36462d5e2e4SEd Tanous asyncResp->res.jsonValue["Id"] = chassisId; 36562d5e2e4SEd Tanous asyncResp->res.jsonValue["Thermal"] = { 3661abe55efSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 3671abe55efSEd Tanous chassisId + "/Thermal"}}; 3682474adfaSEd Tanous // Power object 3692474adfaSEd Tanous asyncResp->res.jsonValue["Power"] = { 3702474adfaSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 3712474adfaSEd Tanous chassisId + "/Power"}}; 37295a3ecadSAnthony Wilson // SensorCollection 37395a3ecadSAnthony Wilson asyncResp->res.jsonValue["Sensors"] = { 37495a3ecadSAnthony Wilson {"@odata.id", "/redfish/v1/Chassis/" + 37595a3ecadSAnthony Wilson chassisId + "/Sensors"}}; 376029573d4SEd Tanous asyncResp->res.jsonValue["Status"] = { 377029573d4SEd Tanous {"State", "Enabled"}, 378029573d4SEd Tanous }; 3792474adfaSEd Tanous 380029573d4SEd Tanous asyncResp->res 381029573d4SEd Tanous .jsonValue["Links"]["ComputerSystems"] = { 3827e860f15SJohn Edward Broadbent {{"@odata.id", 3837e860f15SJohn Edward Broadbent "/redfish/v1/Systems/system"}}}; 3847e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Links"]["ManagedBy"] = 3857e860f15SJohn Edward Broadbent {{{"@odata.id", 3867e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc"}}}; 387beeca0aeSGunnar Mills getChassisState(asyncResp); 388daf36e2eSEd Tanous }, 3897e860f15SJohn Edward Broadbent connectionName, path, 3907e860f15SJohn Edward Broadbent "org.freedesktop.DBus.Properties", "GetAll", 3911abe55efSEd Tanous "xyz.openbmc_project.Inventory.Decorator.Asset"); 392*2c37b4b0SSharad Yadav 393*2c37b4b0SSharad Yadav // Chassis UUID 394*2c37b4b0SSharad Yadav const std::string uuidInterface = 395*2c37b4b0SSharad Yadav "xyz.openbmc_project.Common.UUID"; 396*2c37b4b0SSharad Yadav if (std::find(interfaces2.begin(), interfaces2.end(), 397*2c37b4b0SSharad Yadav uuidInterface) != interfaces2.end()) 398*2c37b4b0SSharad Yadav { 399*2c37b4b0SSharad Yadav crow::connections::systemBus->async_method_call( 400*2c37b4b0SSharad Yadav [asyncResp](const boost::system::error_code ec, 401*2c37b4b0SSharad Yadav const std::variant<std::string>& 402*2c37b4b0SSharad Yadav chassisUUID) { 403*2c37b4b0SSharad Yadav if (ec) 404*2c37b4b0SSharad Yadav { 405*2c37b4b0SSharad Yadav BMCWEB_LOG_DEBUG 406*2c37b4b0SSharad Yadav << "DBUS response error for " 407*2c37b4b0SSharad Yadav "UUID"; 408*2c37b4b0SSharad Yadav messages::internalError(asyncResp->res); 409*2c37b4b0SSharad Yadav return; 410*2c37b4b0SSharad Yadav } 411*2c37b4b0SSharad Yadav const std::string* value = 412*2c37b4b0SSharad Yadav std::get_if<std::string>(&chassisUUID); 413*2c37b4b0SSharad Yadav if (value == nullptr) 414*2c37b4b0SSharad Yadav { 415*2c37b4b0SSharad Yadav BMCWEB_LOG_DEBUG 416*2c37b4b0SSharad Yadav << "Null value returned " 417*2c37b4b0SSharad Yadav "for UUID"; 418*2c37b4b0SSharad Yadav messages::internalError(asyncResp->res); 419*2c37b4b0SSharad Yadav return; 420*2c37b4b0SSharad Yadav } 421*2c37b4b0SSharad Yadav asyncResp->res.jsonValue["UUID"] = *value; 422*2c37b4b0SSharad Yadav }, 423*2c37b4b0SSharad Yadav connectionName, path, 424*2c37b4b0SSharad Yadav "org.freedesktop.DBus.Properties", "Get", 425*2c37b4b0SSharad Yadav uuidInterface, "UUID"); 426*2c37b4b0SSharad Yadav } 427*2c37b4b0SSharad Yadav 428daf36e2eSEd Tanous return; 429daf36e2eSEd Tanous } 430e0d918bcSEd Tanous 431daf36e2eSEd Tanous // Couldn't find an object with that name. return an error 432f12894f8SJason M. Bills messages::resourceNotFound( 4339f8bfa7cSGunnar Mills asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId); 434daf36e2eSEd Tanous }, 435daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", 436daf36e2eSEd Tanous "/xyz/openbmc_project/object_mapper", 437daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTree", 438271584abSEd Tanous "/xyz/openbmc_project/inventory", 0, interfaces); 439c181942fSQiang XU 440c181942fSQiang XU getPhysicalSecurityData(asyncResp); 4417e860f15SJohn Edward Broadbent }); 4421c8fba97SJames Feist 4437e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 4447e860f15SJohn Edward Broadbent .privileges({"ConfigureComponents"}) 4457e860f15SJohn Edward Broadbent .methods( 4467e860f15SJohn Edward Broadbent boost::beast::http::verb:: 4477e860f15SJohn Edward Broadbent patch)([](const crow::Request& req, 4487e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4497e860f15SJohn Edward Broadbent const std::string& param) { 4509f8bfa7cSGunnar Mills std::optional<bool> locationIndicatorActive; 4511c8fba97SJames Feist std::optional<std::string> indicatorLed; 4521c8fba97SJames Feist 4537e860f15SJohn Edward Broadbent if (param.empty()) 4541c8fba97SJames Feist { 4551c8fba97SJames Feist return; 4561c8fba97SJames Feist } 4571c8fba97SJames Feist 4587e860f15SJohn Edward Broadbent if (!json_util::readJson( 4597e860f15SJohn Edward Broadbent req, asyncResp->res, "LocationIndicatorActive", 4607e860f15SJohn Edward Broadbent locationIndicatorActive, "IndicatorLED", indicatorLed)) 4611c8fba97SJames Feist { 4621c8fba97SJames Feist return; 4631c8fba97SJames Feist } 4641c8fba97SJames Feist 4659f8bfa7cSGunnar Mills // TODO (Gunnar): Remove IndicatorLED after enough time has passed 4669f8bfa7cSGunnar Mills if (!locationIndicatorActive && !indicatorLed) 4671c8fba97SJames Feist { 4681c8fba97SJames Feist return; // delete this when we support more patch properties 4691c8fba97SJames Feist } 470d6aa0093SGunnar Mills if (indicatorLed) 471d6aa0093SGunnar Mills { 4727e860f15SJohn Edward Broadbent asyncResp->res.addHeader( 4737e860f15SJohn Edward Broadbent boost::beast::http::field::warning, 474d6aa0093SGunnar Mills "299 - \"IndicatorLED is deprecated. Use " 475d6aa0093SGunnar Mills "LocationIndicatorActive instead.\""); 476d6aa0093SGunnar Mills } 4771c8fba97SJames Feist 4781c8fba97SJames Feist const std::array<const char*, 2> interfaces = { 4791c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board", 4801c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Chassis"}; 4811c8fba97SJames Feist 4827e860f15SJohn Edward Broadbent const std::string& chassisId = param; 4831c8fba97SJames Feist 4841c8fba97SJames Feist crow::connections::systemBus->async_method_call( 4859f8bfa7cSGunnar Mills [asyncResp, chassisId, locationIndicatorActive, indicatorLed]( 4861c8fba97SJames Feist const boost::system::error_code ec, 4871c8fba97SJames Feist const crow::openbmc_mapper::GetSubTreeType& subtree) { 4881c8fba97SJames Feist if (ec) 4891c8fba97SJames Feist { 4901c8fba97SJames Feist messages::internalError(asyncResp->res); 4911c8fba97SJames Feist return; 4921c8fba97SJames Feist } 4931c8fba97SJames Feist 4941c8fba97SJames Feist // Iterate over all retrieved ObjectPaths. 4951c8fba97SJames Feist for (const std::pair< 4961c8fba97SJames Feist std::string, 4977e860f15SJohn Edward Broadbent std::vector<std::pair<std::string, 4987e860f15SJohn Edward Broadbent std::vector<std::string>>>>& 4991214b7e7SGunnar Mills object : subtree) 5001c8fba97SJames Feist { 5011c8fba97SJames Feist const std::string& path = object.first; 5021c8fba97SJames Feist const std::vector< 5031214b7e7SGunnar Mills std::pair<std::string, std::vector<std::string>>>& 5041214b7e7SGunnar Mills connectionNames = object.second; 5051c8fba97SJames Feist 5061c8fba97SJames Feist if (!boost::ends_with(path, chassisId)) 5071c8fba97SJames Feist { 5081c8fba97SJames Feist continue; 5091c8fba97SJames Feist } 5101c8fba97SJames Feist 5111c8fba97SJames Feist if (connectionNames.size() < 1) 5121c8fba97SJames Feist { 5131c8fba97SJames Feist BMCWEB_LOG_ERROR << "Got 0 Connection names"; 5141c8fba97SJames Feist continue; 5151c8fba97SJames Feist } 5161c8fba97SJames Feist 51723a21a1cSEd Tanous const std::vector<std::string>& interfaces3 = 5181c8fba97SJames Feist connectionNames[0].second; 5191c8fba97SJames Feist 5201c8fba97SJames Feist const std::array<const char*, 2> hasIndicatorLed = { 5211c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 5221c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board." 5231c8fba97SJames Feist "Motherboard"}; 5241c8fba97SJames Feist bool indicatorChassis = false; 5251c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 5261c8fba97SJames Feist { 5277e860f15SJohn Edward Broadbent if (std::find(interfaces3.begin(), 5287e860f15SJohn Edward Broadbent interfaces3.end(), 52923a21a1cSEd Tanous interface) != interfaces3.end()) 5301c8fba97SJames Feist { 5311c8fba97SJames Feist indicatorChassis = true; 5321c8fba97SJames Feist break; 5331c8fba97SJames Feist } 5341c8fba97SJames Feist } 5359f8bfa7cSGunnar Mills if (locationIndicatorActive) 5369f8bfa7cSGunnar Mills { 5379f8bfa7cSGunnar Mills if (indicatorChassis) 5389f8bfa7cSGunnar Mills { 5399f8bfa7cSGunnar Mills setLocationIndicatorActive( 5409f8bfa7cSGunnar Mills asyncResp, *locationIndicatorActive); 5419f8bfa7cSGunnar Mills } 5429f8bfa7cSGunnar Mills else 5439f8bfa7cSGunnar Mills { 5449f8bfa7cSGunnar Mills messages::propertyUnknown( 5459f8bfa7cSGunnar Mills asyncResp->res, "LocationIndicatorActive"); 5469f8bfa7cSGunnar Mills } 5479f8bfa7cSGunnar Mills } 5489f8bfa7cSGunnar Mills if (indicatorLed) 5499f8bfa7cSGunnar Mills { 5501c8fba97SJames Feist if (indicatorChassis) 5511c8fba97SJames Feist { 552f23b7296SEd Tanous setIndicatorLedState(asyncResp, *indicatorLed); 5531c8fba97SJames Feist } 5541c8fba97SJames Feist else 5551c8fba97SJames Feist { 5561c8fba97SJames Feist messages::propertyUnknown(asyncResp->res, 5571c8fba97SJames Feist "IndicatorLED"); 5581c8fba97SJames Feist } 5591c8fba97SJames Feist } 5601c8fba97SJames Feist return; 5611c8fba97SJames Feist } 5621c8fba97SJames Feist 5631c8fba97SJames Feist messages::resourceNotFound( 5649f8bfa7cSGunnar Mills asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId); 5651c8fba97SJames Feist }, 5661c8fba97SJames Feist "xyz.openbmc_project.ObjectMapper", 5671c8fba97SJames Feist "/xyz/openbmc_project/object_mapper", 5681c8fba97SJames Feist "xyz.openbmc_project.ObjectMapper", "GetSubTree", 5691c8fba97SJames Feist "/xyz/openbmc_project/inventory", 0, interfaces); 5707e860f15SJohn Edward Broadbent }); 5711c8fba97SJames Feist } 572dd99e04bSP.K. Lee 5738d1b46d7Szhanghch05 inline void 5748d1b46d7Szhanghch05 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 575dd99e04bSP.K. Lee { 576c3b3c92aSVijay Khemka const char* busName = "xyz.openbmc_project.ObjectMapper"; 577c3b3c92aSVijay Khemka const char* path = "/xyz/openbmc_project/object_mapper"; 578c3b3c92aSVijay Khemka const char* interface = "xyz.openbmc_project.ObjectMapper"; 579c3b3c92aSVijay Khemka const char* method = "GetSubTreePaths"; 580c3b3c92aSVijay Khemka 581c3b3c92aSVijay Khemka const std::array<const char*, 1> interfaces = { 582c3b3c92aSVijay Khemka "xyz.openbmc_project.State.Chassis"}; 583c3b3c92aSVijay Khemka 584c3b3c92aSVijay Khemka // Use mapper to get subtree paths. 585c3b3c92aSVijay Khemka crow::connections::systemBus->async_method_call( 586c3b3c92aSVijay Khemka [asyncResp](const boost::system::error_code ec, 587c3b3c92aSVijay Khemka const std::vector<std::string>& chassisList) { 588c3b3c92aSVijay Khemka if (ec) 589c3b3c92aSVijay Khemka { 590c3b3c92aSVijay Khemka BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec; 591c3b3c92aSVijay Khemka messages::internalError(asyncResp->res); 592c3b3c92aSVijay Khemka return; 593c3b3c92aSVijay Khemka } 594c3b3c92aSVijay Khemka 595dd99e04bSP.K. Lee const char* processName = "xyz.openbmc_project.State.Chassis"; 596dd99e04bSP.K. Lee const char* interfaceName = "xyz.openbmc_project.State.Chassis"; 597dd99e04bSP.K. Lee const char* destProperty = "RequestedPowerTransition"; 598dd99e04bSP.K. Lee const std::string propertyValue = 599dd99e04bSP.K. Lee "xyz.openbmc_project.State.Chassis.Transition.PowerCycle"; 600c3b3c92aSVijay Khemka std::string objectPath = 601c3b3c92aSVijay Khemka "/xyz/openbmc_project/state/chassis_system0"; 602c3b3c92aSVijay Khemka 603c3b3c92aSVijay Khemka /* Look for system reset chassis path */ 604c3b3c92aSVijay Khemka if ((std::find(chassisList.begin(), chassisList.end(), 605c3b3c92aSVijay Khemka objectPath)) == chassisList.end()) 606c3b3c92aSVijay Khemka { 607c3b3c92aSVijay Khemka /* We prefer to reset the full chassis_system, but if it doesn't 608c3b3c92aSVijay Khemka * exist on some platforms, fall back to a host-only power reset 609c3b3c92aSVijay Khemka */ 610c3b3c92aSVijay Khemka objectPath = "/xyz/openbmc_project/state/chassis0"; 611c3b3c92aSVijay Khemka } 612dd99e04bSP.K. Lee 613dd99e04bSP.K. Lee crow::connections::systemBus->async_method_call( 614dd99e04bSP.K. Lee [asyncResp](const boost::system::error_code ec) { 615dd99e04bSP.K. Lee // Use "Set" method to set the property value. 616dd99e04bSP.K. Lee if (ec) 617dd99e04bSP.K. Lee { 618c3b3c92aSVijay Khemka BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: " 619c3b3c92aSVijay Khemka << ec; 620dd99e04bSP.K. Lee messages::internalError(asyncResp->res); 621dd99e04bSP.K. Lee return; 622dd99e04bSP.K. Lee } 623dd99e04bSP.K. Lee 624dd99e04bSP.K. Lee messages::success(asyncResp->res); 625dd99e04bSP.K. Lee }, 626c3b3c92aSVijay Khemka processName, objectPath, "org.freedesktop.DBus.Properties", 627c3b3c92aSVijay Khemka "Set", interfaceName, destProperty, 628c3b3c92aSVijay Khemka std::variant<std::string>{propertyValue}); 629c3b3c92aSVijay Khemka }, 630c3b3c92aSVijay Khemka busName, path, interface, method, "/", 0, interfaces); 631dd99e04bSP.K. Lee } 632dd99e04bSP.K. Lee 633dd99e04bSP.K. Lee /** 634dd99e04bSP.K. Lee * ChassisResetAction class supports the POST method for the Reset 635dd99e04bSP.K. Lee * action. 636dd99e04bSP.K. Lee * Function handles POST method request. 637dd99e04bSP.K. Lee * Analyzes POST body before sending Reset request data to D-Bus. 638dd99e04bSP.K. Lee */ 6397e860f15SJohn Edward Broadbent 6407e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetAction(App& app) 641dd99e04bSP.K. Lee { 6427e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/") 6437e860f15SJohn Edward Broadbent .privileges({"ConfigureComponents"}) 6447e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 6457e860f15SJohn Edward Broadbent [](const crow::Request& req, 6467e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6477e860f15SJohn Edward Broadbent const std::string&) { 648dd99e04bSP.K. Lee BMCWEB_LOG_DEBUG << "Post Chassis Reset."; 649dd99e04bSP.K. Lee 650dd99e04bSP.K. Lee std::string resetType; 651dd99e04bSP.K. Lee 6527e860f15SJohn Edward Broadbent if (!json_util::readJson(req, asyncResp->res, "ResetType", 6537e860f15SJohn Edward Broadbent resetType)) 654dd99e04bSP.K. Lee { 655dd99e04bSP.K. Lee return; 656dd99e04bSP.K. Lee } 657dd99e04bSP.K. Lee 658dd99e04bSP.K. Lee if (resetType != "PowerCycle") 659dd99e04bSP.K. Lee { 660dd99e04bSP.K. Lee BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: " 661dd99e04bSP.K. Lee << resetType; 6627e860f15SJohn Edward Broadbent messages::actionParameterNotSupported( 6637e860f15SJohn Edward Broadbent asyncResp->res, resetType, "ResetType"); 664dd99e04bSP.K. Lee 665dd99e04bSP.K. Lee return; 666dd99e04bSP.K. Lee } 667dd99e04bSP.K. Lee doChassisPowerCycle(asyncResp); 6687e860f15SJohn Edward Broadbent }); 669dd99e04bSP.K. Lee } 6701cb1a9e6SAppaRao Puli 6711cb1a9e6SAppaRao Puli /** 6721cb1a9e6SAppaRao Puli * ChassisResetActionInfo derived class for delivering Chassis 6731cb1a9e6SAppaRao Puli * ResetType AllowableValues using ResetInfo schema. 6741cb1a9e6SAppaRao Puli */ 6757e860f15SJohn Edward Broadbent inline void requestRoutesChassisResetActionInfo(App& app) 6761cb1a9e6SAppaRao Puli { 6777e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/") 6787e860f15SJohn Edward Broadbent .privileges({"Login"}) 6797e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 6807e860f15SJohn Edward Broadbent [](const crow::Request&, 6817e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6827e860f15SJohn Edward Broadbent const std::string& chassisId) 6831cb1a9e6SAppaRao Puli 6841cb1a9e6SAppaRao Puli { 6858d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 6868d1b46d7Szhanghch05 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"}, 6878d1b46d7Szhanghch05 {"@odata.id", 6888d1b46d7Szhanghch05 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"}, 6891cb1a9e6SAppaRao Puli {"Name", "Reset Action Info"}, 6901cb1a9e6SAppaRao Puli {"Id", "ResetActionInfo"}, 6911cb1a9e6SAppaRao Puli {"Parameters", 6921cb1a9e6SAppaRao Puli {{{"Name", "ResetType"}, 6931cb1a9e6SAppaRao Puli {"Required", true}, 6941cb1a9e6SAppaRao Puli {"DataType", "String"}, 6951cb1a9e6SAppaRao Puli {"AllowableValues", {"PowerCycle"}}}}}}; 6967e860f15SJohn Edward Broadbent }); 6971cb1a9e6SAppaRao Puli } 6981cb1a9e6SAppaRao Puli 699e37f8451SRapkiewicz, Pawel } // namespace redfish 700