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 3204a258f4SEd Tanous using VariantType = sdbusplus::message::variant<bool, std::string, uint64_t>; 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 { 48e0d918bcSEd Tanous entityPrivileges = { 49e0d918bcSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 50e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 51e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 52e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 53e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 54e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 55e37f8451SRapkiewicz, Pawel } 56e37f8451SRapkiewicz, Pawel 57e37f8451SRapkiewicz, Pawel private: 58e37f8451SRapkiewicz, Pawel /** 59e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 60e37f8451SRapkiewicz, Pawel */ 6155c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 621abe55efSEd Tanous const std::vector<std::string> ¶ms) override 631abe55efSEd Tanous { 6462d5e2e4SEd Tanous const std::array<const char *, 4> interfaces = { 6562d5e2e4SEd Tanous "xyz.openbmc_project.Inventory.Item.Board", 6662d5e2e4SEd Tanous "xyz.openbmc_project.Inventory.Item.Chassis", 6762d5e2e4SEd Tanous "xyz.openbmc_project.Inventory.Item.PowerSupply", 6862d5e2e4SEd Tanous "xyz.openbmc_project.Inventory.Item.System", 6962d5e2e4SEd Tanous }; 70*0f74e643SEd Tanous res.jsonValue["@odata.type"] = "#ChassisCollection.ChassisCollection"; 71*0f74e643SEd Tanous res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 72*0f74e643SEd Tanous res.jsonValue["@odata.context"] = 73*0f74e643SEd Tanous "/redfish/v1/$metadata#ChassisCollection.ChassisCollection"; 74*0f74e643SEd Tanous res.jsonValue["Name"] = "Chassis Collection"; 75*0f74e643SEd Tanous 7662d5e2e4SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 7762d5e2e4SEd Tanous crow::connections::systemBus->async_method_call( 7862d5e2e4SEd Tanous [asyncResp](const boost::system::error_code ec, 7962d5e2e4SEd Tanous const std::vector<std::string> &chassisList) { 8062d5e2e4SEd Tanous if (ec) 811abe55efSEd Tanous { 82f12894f8SJason M. Bills messages::internalError(asyncResp->res); 8362d5e2e4SEd Tanous return; 84e37f8451SRapkiewicz, Pawel } 8562d5e2e4SEd Tanous nlohmann::json &chassisArray = 8662d5e2e4SEd Tanous asyncResp->res.jsonValue["Members"]; 8762d5e2e4SEd Tanous chassisArray = nlohmann::json::array(); 8862d5e2e4SEd Tanous for (const std::string &objpath : chassisList) 8962d5e2e4SEd Tanous { 9062d5e2e4SEd Tanous std::size_t lastPos = objpath.rfind("/"); 9162d5e2e4SEd Tanous if (lastPos == std::string::npos) 9262d5e2e4SEd Tanous { 9362d5e2e4SEd Tanous BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath; 9462d5e2e4SEd Tanous continue; 9562d5e2e4SEd Tanous } 9662d5e2e4SEd Tanous chassisArray.push_back( 9762d5e2e4SEd Tanous {{"@odata.id", "/redfish/v1/Chassis/" + 9862d5e2e4SEd Tanous objpath.substr(lastPos + 1)}}); 99e37f8451SRapkiewicz, Pawel } 100e37f8451SRapkiewicz, Pawel 10162d5e2e4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 10262d5e2e4SEd Tanous chassisArray.size(); 10362d5e2e4SEd Tanous }, 10462d5e2e4SEd Tanous "xyz.openbmc_project.ObjectMapper", 10562d5e2e4SEd Tanous "/xyz/openbmc_project/object_mapper", 10662d5e2e4SEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 10762d5e2e4SEd Tanous "/xyz/openbmc_project/inventory", int32_t(3), interfaces); 10862d5e2e4SEd Tanous } 109e37f8451SRapkiewicz, Pawel }; 110e37f8451SRapkiewicz, Pawel 111e37f8451SRapkiewicz, Pawel /** 112e37f8451SRapkiewicz, Pawel * Chassis override class for delivering Chassis Schema 113e37f8451SRapkiewicz, Pawel */ 1141abe55efSEd Tanous class Chassis : public Node 1151abe55efSEd Tanous { 116e37f8451SRapkiewicz, Pawel public: 1171abe55efSEd Tanous Chassis(CrowApp &app) : 1181abe55efSEd Tanous Node(app, "/redfish/v1/Chassis/<str>/", std::string()) 1191abe55efSEd Tanous { 120e0d918bcSEd Tanous entityPrivileges = { 121e0d918bcSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 122e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 123e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 124e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 125e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 126e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 127e37f8451SRapkiewicz, Pawel } 128e37f8451SRapkiewicz, Pawel 129e37f8451SRapkiewicz, Pawel private: 130e37f8451SRapkiewicz, Pawel /** 131e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 132e37f8451SRapkiewicz, Pawel */ 13355c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 1341abe55efSEd Tanous const std::vector<std::string> ¶ms) override 1351abe55efSEd Tanous { 136e37f8451SRapkiewicz, Pawel // Check if there is required param, truly entering this shall be 137e37f8451SRapkiewicz, Pawel // impossible. 1381abe55efSEd Tanous if (params.size() != 1) 1391abe55efSEd Tanous { 140f12894f8SJason M. Bills messages::internalError(res); 141e37f8451SRapkiewicz, Pawel res.end(); 142e37f8451SRapkiewicz, Pawel return; 143e37f8451SRapkiewicz, Pawel } 144e37f8451SRapkiewicz, Pawel 145*0f74e643SEd Tanous res.jsonValue["@odata.type"] = "#Chassis.v1_4_0.Chassis"; 146*0f74e643SEd Tanous res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 147*0f74e643SEd Tanous res.jsonValue["@odata.context"] = 148*0f74e643SEd Tanous "/redfish/v1/$metadata#Chassis.Chassis"; 149*0f74e643SEd Tanous res.jsonValue["Name"] = "Chassis Collection"; 150*0f74e643SEd Tanous res.jsonValue["ChassisType"] = "RackMount"; 151*0f74e643SEd Tanous res.jsonValue["PowerState"] = "On"; 152*0f74e643SEd Tanous 15355c7b7a2SEd Tanous const std::string &chassisId = params[0]; 15462d5e2e4SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 15555c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 15662d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 15762d5e2e4SEd Tanous const boost::system::error_code ec, 158daf36e2eSEd Tanous const std::vector<std::pair< 1591abe55efSEd Tanous std::string, std::vector<std::pair< 1601abe55efSEd Tanous std::string, std::vector<std::string>>>>> 161daf36e2eSEd Tanous &subtree) { 16262d5e2e4SEd Tanous if (ec) 1631abe55efSEd Tanous { 164f12894f8SJason M. Bills messages::internalError(asyncResp->res); 165daf36e2eSEd Tanous return; 166daf36e2eSEd Tanous } 167daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 1681abe55efSEd Tanous for (const std::pair< 1691abe55efSEd Tanous std::string, 1701abe55efSEd Tanous std::vector< 1711abe55efSEd Tanous std::pair<std::string, std::vector<std::string>>>> 1721abe55efSEd Tanous &object : subtree) 1731abe55efSEd Tanous { 174daf36e2eSEd Tanous const std::string &path = object.first; 1751abe55efSEd Tanous const std::vector< 1761abe55efSEd Tanous std::pair<std::string, std::vector<std::string>>> 177daf36e2eSEd Tanous &connectionNames = object.second; 178e0d918bcSEd Tanous 1791abe55efSEd Tanous if (!boost::ends_with(path, chassisId)) 1801abe55efSEd Tanous { 181daf36e2eSEd Tanous continue; 182daf36e2eSEd Tanous } 1831abe55efSEd Tanous if (connectionNames.size() < 1) 1841abe55efSEd Tanous { 1851abe55efSEd Tanous BMCWEB_LOG_ERROR << "Only got " 1861abe55efSEd Tanous << connectionNames.size() 18755c7b7a2SEd Tanous << " Connection names"; 188e0d918bcSEd Tanous continue; 189daf36e2eSEd Tanous } 190e0d918bcSEd Tanous 191daf36e2eSEd Tanous const std::string connectionName = connectionNames[0].first; 19255c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 19362d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 19462d5e2e4SEd Tanous const boost::system::error_code ec, 1951abe55efSEd Tanous const std::vector<std::pair< 1961abe55efSEd Tanous std::string, VariantType>> &propertiesList) { 1971abe55efSEd Tanous for (const std::pair<std::string, VariantType> 1981abe55efSEd Tanous &property : propertiesList) 1991abe55efSEd Tanous { 200daf36e2eSEd Tanous const std::string *value = 2011abe55efSEd Tanous mapbox::getPtr<const std::string>( 2021abe55efSEd Tanous property.second); 2031abe55efSEd Tanous if (value != nullptr) 2041abe55efSEd Tanous { 20562d5e2e4SEd Tanous asyncResp->res.jsonValue[property.first] = 20662d5e2e4SEd Tanous *value; 207daf36e2eSEd Tanous } 208daf36e2eSEd Tanous } 20962d5e2e4SEd Tanous asyncResp->res.jsonValue["Name"] = chassisId; 21062d5e2e4SEd Tanous asyncResp->res.jsonValue["Id"] = chassisId; 21162d5e2e4SEd Tanous asyncResp->res.jsonValue["Thermal"] = { 2121abe55efSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 2131abe55efSEd Tanous chassisId + "/Thermal"}}; 2142474adfaSEd Tanous // Power object 2152474adfaSEd Tanous asyncResp->res.jsonValue["Power"] = { 2162474adfaSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 2172474adfaSEd Tanous chassisId + "/Power"}}; 2182474adfaSEd Tanous 2192474adfaSEd Tanous // TODO: An array of references to computer systems 2202474adfaSEd Tanous // contained in this chassis. 2212474adfaSEd Tanous // res.jsonValue["Links"]["ComputerSystems"] 2222474adfaSEd Tanous // = 2232474adfaSEd Tanous // {{{"@odata.id", 2242474adfaSEd Tanous // "/redfish/v1/Systems/1"}}}; 2252474adfaSEd Tanous // An array of references to the Managers 2262474adfaSEd Tanous // responsible for managing this chassis. 2272474adfaSEd Tanous // res.jsonValue["Links"]["ManagedBy"] = 2282474adfaSEd Tanous // {{{"@odata.id", 2292474adfaSEd Tanous // "/redfish/v1/Managers/1"}}}; 230daf36e2eSEd Tanous }, 231daf36e2eSEd Tanous connectionName, path, "org.freedesktop.DBus.Properties", 2321abe55efSEd Tanous "GetAll", 2331abe55efSEd Tanous "xyz.openbmc_project.Inventory.Decorator.Asset"); 234daf36e2eSEd Tanous return; 235daf36e2eSEd Tanous } 236e0d918bcSEd Tanous 237daf36e2eSEd Tanous // Couldn't find an object with that name. return an error 238f12894f8SJason M. Bills messages::resourceNotFound( 239f12894f8SJason M. Bills asyncResp->res, "#Chassis.v1_4_0.Chassis", chassisId); 240daf36e2eSEd Tanous }, 241daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", 242daf36e2eSEd Tanous "/xyz/openbmc_project/object_mapper", 243daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTree", 244daf36e2eSEd Tanous "/xyz/openbmc_project/inventory", int32_t(0), 245daf36e2eSEd Tanous std::array<const char *, 1>{ 246daf36e2eSEd Tanous "xyz.openbmc_project.Inventory.Decorator.Asset"}); 247e37f8451SRapkiewicz, Pawel } 24862d5e2e4SEd Tanous }; 249e37f8451SRapkiewicz, Pawel } // namespace redfish 250