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 18e37f8451SRapkiewicz, Pawel #include "node.hpp" 191abe55efSEd Tanous 20e37f8451SRapkiewicz, Pawel #include <boost/container/flat_map.hpp> 21e37f8451SRapkiewicz, Pawel 221abe55efSEd Tanous namespace redfish 231abe55efSEd Tanous { 24e37f8451SRapkiewicz, Pawel 25e37f8451SRapkiewicz, Pawel /** 26e37f8451SRapkiewicz, Pawel * DBus types primitives for several generic DBus interfaces 27e37f8451SRapkiewicz, Pawel * TODO(Pawel) consider move this to separate file into boost::dbus 28e37f8451SRapkiewicz, Pawel */ 2955c7b7a2SEd Tanous // Note, this is not a very useful Variant, but because it isn't used to get 30aa2e59c1SEd Tanous // values, it should be as simple as possible 31aa2e59c1SEd Tanous // TODO(ed) invent a nullvariant type 32c5b2abe0SLewanczyk, Dawid using VariantType = sdbusplus::message::variant<bool, std::string>; 33aa2e59c1SEd Tanous using ManagedObjectsType = std::vector<std::pair< 34aa2e59c1SEd Tanous sdbusplus::message::object_path, 35aa2e59c1SEd Tanous std::vector<std::pair<std::string, 36aa2e59c1SEd Tanous std::vector<std::pair<std::string, VariantType>>>>>>; 37e37f8451SRapkiewicz, Pawel 38aa2e59c1SEd Tanous using PropertiesType = boost::container::flat_map<std::string, VariantType>; 39e37f8451SRapkiewicz, Pawel 40e37f8451SRapkiewicz, Pawel /** 41e37f8451SRapkiewicz, Pawel * ChassisCollection derived class for delivering Chassis Collection Schema 42e37f8451SRapkiewicz, Pawel */ 431abe55efSEd Tanous class ChassisCollection : public Node 441abe55efSEd Tanous { 45e37f8451SRapkiewicz, Pawel public: 461abe55efSEd Tanous ChassisCollection(CrowApp &app) : Node(app, "/redfish/v1/Chassis/") 471abe55efSEd Tanous { 48e37f8451SRapkiewicz, Pawel Node::json["@odata.type"] = "#ChassisCollection.ChassisCollection"; 49e37f8451SRapkiewicz, Pawel Node::json["@odata.id"] = "/redfish/v1/Chassis"; 50e37f8451SRapkiewicz, Pawel Node::json["@odata.context"] = 51e37f8451SRapkiewicz, Pawel "/redfish/v1/$metadata#ChassisCollection.ChassisCollection"; 52e37f8451SRapkiewicz, Pawel Node::json["Name"] = "Chassis Collection"; 53e37f8451SRapkiewicz, Pawel 54e0d918bcSEd Tanous entityPrivileges = { 55e0d918bcSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 56e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 57e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 58e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 59e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 60e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 61e37f8451SRapkiewicz, Pawel } 62e37f8451SRapkiewicz, Pawel 63e37f8451SRapkiewicz, Pawel private: 64e37f8451SRapkiewicz, Pawel /** 65e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 66e37f8451SRapkiewicz, Pawel */ 6755c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 681abe55efSEd Tanous const std::vector<std::string> ¶ms) override 691abe55efSEd Tanous { 70*62d5e2e4SEd Tanous const std::array<const char *, 4> interfaces = { 71*62d5e2e4SEd Tanous "xyz.openbmc_project.Inventory.Item.Board", 72*62d5e2e4SEd Tanous "xyz.openbmc_project.Inventory.Item.Chassis", 73*62d5e2e4SEd Tanous "xyz.openbmc_project.Inventory.Item.PowerSupply", 74*62d5e2e4SEd Tanous "xyz.openbmc_project.Inventory.Item.System", 75*62d5e2e4SEd Tanous }; 7655c7b7a2SEd Tanous res.jsonValue = Node::json; 77*62d5e2e4SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 78*62d5e2e4SEd Tanous crow::connections::systemBus->async_method_call( 79*62d5e2e4SEd Tanous [asyncResp](const boost::system::error_code ec, 80*62d5e2e4SEd Tanous const std::vector<std::string> &chassisList) { 81*62d5e2e4SEd Tanous if (ec) 821abe55efSEd Tanous { 83*62d5e2e4SEd Tanous messages::addMessageToErrorJson(asyncResp->res.jsonValue, 84*62d5e2e4SEd Tanous messages::internalError()); 85*62d5e2e4SEd Tanous asyncResp->res.result( 861abe55efSEd Tanous boost::beast::http::status::internal_server_error); 87*62d5e2e4SEd Tanous return; 88e37f8451SRapkiewicz, Pawel } 89*62d5e2e4SEd Tanous nlohmann::json &chassisArray = 90*62d5e2e4SEd Tanous asyncResp->res.jsonValue["Members"]; 91*62d5e2e4SEd Tanous chassisArray = nlohmann::json::array(); 92*62d5e2e4SEd Tanous for (const std::string &objpath : chassisList) 93*62d5e2e4SEd Tanous { 94*62d5e2e4SEd Tanous std::size_t lastPos = objpath.rfind("/"); 95*62d5e2e4SEd Tanous if (lastPos == std::string::npos) 96*62d5e2e4SEd Tanous { 97*62d5e2e4SEd Tanous BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath; 98*62d5e2e4SEd Tanous continue; 99*62d5e2e4SEd Tanous } 100*62d5e2e4SEd Tanous chassisArray.push_back( 101*62d5e2e4SEd Tanous {{"@odata.id", "/redfish/v1/Chassis/" + 102*62d5e2e4SEd Tanous objpath.substr(lastPos + 1)}}); 103e37f8451SRapkiewicz, Pawel } 104e37f8451SRapkiewicz, Pawel 105*62d5e2e4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 106*62d5e2e4SEd Tanous chassisArray.size(); 107*62d5e2e4SEd Tanous }, 108*62d5e2e4SEd Tanous "xyz.openbmc_project.ObjectMapper", 109*62d5e2e4SEd Tanous "/xyz/openbmc_project/object_mapper", 110*62d5e2e4SEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 111*62d5e2e4SEd Tanous "/xyz/openbmc_project/inventory", int32_t(3), interfaces); 112*62d5e2e4SEd Tanous } 113e37f8451SRapkiewicz, Pawel }; 114e37f8451SRapkiewicz, Pawel 115e37f8451SRapkiewicz, Pawel /** 116e37f8451SRapkiewicz, Pawel * Chassis override class for delivering Chassis Schema 117e37f8451SRapkiewicz, Pawel */ 1181abe55efSEd Tanous class Chassis : public Node 1191abe55efSEd Tanous { 120e37f8451SRapkiewicz, Pawel public: 1211abe55efSEd Tanous Chassis(CrowApp &app) : 1221abe55efSEd Tanous Node(app, "/redfish/v1/Chassis/<str>/", std::string()) 1231abe55efSEd Tanous { 124e37f8451SRapkiewicz, Pawel Node::json["@odata.type"] = "#Chassis.v1_4_0.Chassis"; 125e37f8451SRapkiewicz, Pawel Node::json["@odata.id"] = "/redfish/v1/Chassis"; 126e37f8451SRapkiewicz, Pawel Node::json["@odata.context"] = "/redfish/v1/$metadata#Chassis.Chassis"; 127e37f8451SRapkiewicz, Pawel Node::json["Name"] = "Chassis Collection"; 1286c233015SEd Tanous Node::json["ChassisType"] = "RackMount"; 129e37f8451SRapkiewicz, Pawel 130e0d918bcSEd Tanous entityPrivileges = { 131e0d918bcSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 132e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 133e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 134e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 135e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 136e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 137e37f8451SRapkiewicz, Pawel } 138e37f8451SRapkiewicz, Pawel 139e37f8451SRapkiewicz, Pawel private: 140e37f8451SRapkiewicz, Pawel /** 141e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 142e37f8451SRapkiewicz, Pawel */ 14355c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 1441abe55efSEd Tanous const std::vector<std::string> ¶ms) override 1451abe55efSEd Tanous { 146e37f8451SRapkiewicz, Pawel // Check if there is required param, truly entering this shall be 147e37f8451SRapkiewicz, Pawel // impossible. 1481abe55efSEd Tanous if (params.size() != 1) 1491abe55efSEd Tanous { 150e0d918bcSEd Tanous res.result(boost::beast::http::status::internal_server_error); 151e37f8451SRapkiewicz, Pawel res.end(); 152e37f8451SRapkiewicz, Pawel return; 153e37f8451SRapkiewicz, Pawel } 154e37f8451SRapkiewicz, Pawel 15555c7b7a2SEd Tanous res.jsonValue = Node::json; 15655c7b7a2SEd Tanous const std::string &chassisId = params[0]; 157*62d5e2e4SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 15855c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 159*62d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 160*62d5e2e4SEd Tanous const boost::system::error_code ec, 161daf36e2eSEd Tanous const std::vector<std::pair< 1621abe55efSEd Tanous std::string, std::vector<std::pair< 1631abe55efSEd Tanous std::string, std::vector<std::string>>>>> 164daf36e2eSEd Tanous &subtree) { 165*62d5e2e4SEd Tanous if (ec) 1661abe55efSEd Tanous { 167*62d5e2e4SEd Tanous messages::addMessageToErrorJson(asyncResp->res.jsonValue, 168*62d5e2e4SEd Tanous messages::internalError()); 169*62d5e2e4SEd Tanous asyncResp->res.result( 1701abe55efSEd Tanous boost::beast::http::status::internal_server_error); 171daf36e2eSEd Tanous return; 172daf36e2eSEd Tanous } 173daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 1741abe55efSEd Tanous for (const std::pair< 1751abe55efSEd Tanous std::string, 1761abe55efSEd Tanous std::vector< 1771abe55efSEd Tanous std::pair<std::string, std::vector<std::string>>>> 1781abe55efSEd Tanous &object : subtree) 1791abe55efSEd Tanous { 180daf36e2eSEd Tanous const std::string &path = object.first; 1811abe55efSEd Tanous const std::vector< 1821abe55efSEd Tanous std::pair<std::string, std::vector<std::string>>> 183daf36e2eSEd Tanous &connectionNames = object.second; 184e0d918bcSEd Tanous 1851abe55efSEd Tanous if (!boost::ends_with(path, chassisId)) 1861abe55efSEd Tanous { 187daf36e2eSEd Tanous continue; 188daf36e2eSEd Tanous } 1891abe55efSEd Tanous if (connectionNames.size() < 1) 1901abe55efSEd Tanous { 1911abe55efSEd Tanous BMCWEB_LOG_ERROR << "Only got " 1921abe55efSEd Tanous << connectionNames.size() 19355c7b7a2SEd Tanous << " Connection names"; 194e0d918bcSEd Tanous continue; 195daf36e2eSEd Tanous } 196e0d918bcSEd Tanous 197daf36e2eSEd Tanous const std::string connectionName = connectionNames[0].first; 19855c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 199*62d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 200*62d5e2e4SEd Tanous const boost::system::error_code ec, 2011abe55efSEd Tanous const std::vector<std::pair< 2021abe55efSEd Tanous std::string, VariantType>> &propertiesList) { 2031abe55efSEd Tanous for (const std::pair<std::string, VariantType> 2041abe55efSEd Tanous &property : propertiesList) 2051abe55efSEd Tanous { 206daf36e2eSEd Tanous const std::string *value = 2071abe55efSEd Tanous mapbox::getPtr<const std::string>( 2081abe55efSEd Tanous property.second); 2091abe55efSEd Tanous if (value != nullptr) 2101abe55efSEd Tanous { 211*62d5e2e4SEd Tanous asyncResp->res.jsonValue[property.first] = 212*62d5e2e4SEd Tanous *value; 213daf36e2eSEd Tanous } 214daf36e2eSEd Tanous } 215*62d5e2e4SEd Tanous asyncResp->res.jsonValue["Name"] = chassisId; 216*62d5e2e4SEd Tanous asyncResp->res.jsonValue["Id"] = chassisId; 217*62d5e2e4SEd Tanous asyncResp->res.jsonValue["Thermal"] = { 2181abe55efSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 2191abe55efSEd Tanous chassisId + "/Thermal"}}; 220daf36e2eSEd Tanous }, 221daf36e2eSEd Tanous connectionName, path, "org.freedesktop.DBus.Properties", 2221abe55efSEd Tanous "GetAll", 2231abe55efSEd Tanous "xyz.openbmc_project.Inventory.Decorator.Asset"); 224daf36e2eSEd Tanous return; 225daf36e2eSEd Tanous } 226e0d918bcSEd Tanous 227daf36e2eSEd Tanous // Couldn't find an object with that name. return an error 228*62d5e2e4SEd Tanous asyncResp->res.jsonValue = redfish::messages::resourceNotFound( 229*62d5e2e4SEd Tanous "#Chassis.v1_4_0.Chassis", chassisId); 230*62d5e2e4SEd Tanous asyncResp->res.result(boost::beast::http::status::not_found); 231daf36e2eSEd Tanous }, 232daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", 233daf36e2eSEd Tanous "/xyz/openbmc_project/object_mapper", 234daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTree", 235daf36e2eSEd Tanous "/xyz/openbmc_project/inventory", int32_t(0), 236daf36e2eSEd Tanous std::array<const char *, 1>{ 237daf36e2eSEd Tanous "xyz.openbmc_project.Inventory.Decorator.Asset"}); 238e37f8451SRapkiewicz, Pawel } 239*62d5e2e4SEd Tanous }; 240e37f8451SRapkiewicz, Pawel } // namespace redfish 241