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> 21abf2add6SEd Tanous #include <variant> 22e37f8451SRapkiewicz, Pawel 231abe55efSEd Tanous namespace redfish 241abe55efSEd Tanous { 25e37f8451SRapkiewicz, Pawel 26e37f8451SRapkiewicz, Pawel /** 27e37f8451SRapkiewicz, Pawel * DBus types primitives for several generic DBus interfaces 28e37f8451SRapkiewicz, Pawel * TODO(Pawel) consider move this to separate file into boost::dbus 29e37f8451SRapkiewicz, Pawel */ 3055c7b7a2SEd Tanous // Note, this is not a very useful Variant, but because it isn't used to get 31aa2e59c1SEd Tanous // values, it should be as simple as possible 32aa2e59c1SEd Tanous // TODO(ed) invent a nullvariant type 33abf2add6SEd Tanous using VariantType = std::variant<bool, std::string, uint64_t>; 34aa2e59c1SEd Tanous using ManagedObjectsType = std::vector<std::pair< 35aa2e59c1SEd Tanous sdbusplus::message::object_path, 36aa2e59c1SEd Tanous std::vector<std::pair<std::string, 37aa2e59c1SEd Tanous std::vector<std::pair<std::string, VariantType>>>>>>; 38e37f8451SRapkiewicz, Pawel 39aa2e59c1SEd Tanous using PropertiesType = boost::container::flat_map<std::string, VariantType>; 40e37f8451SRapkiewicz, Pawel 41e37f8451SRapkiewicz, Pawel /** 42e37f8451SRapkiewicz, Pawel * ChassisCollection derived class for delivering Chassis Collection Schema 43e37f8451SRapkiewicz, Pawel */ 441abe55efSEd Tanous class ChassisCollection : public Node 451abe55efSEd Tanous { 46e37f8451SRapkiewicz, Pawel public: 471abe55efSEd Tanous ChassisCollection(CrowApp &app) : Node(app, "/redfish/v1/Chassis/") 481abe55efSEd Tanous { 49e0d918bcSEd Tanous entityPrivileges = { 50e0d918bcSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 51e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 52e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 53e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 54e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 55e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 56e37f8451SRapkiewicz, Pawel } 57e37f8451SRapkiewicz, Pawel 58e37f8451SRapkiewicz, Pawel private: 59e37f8451SRapkiewicz, Pawel /** 60e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 61e37f8451SRapkiewicz, Pawel */ 6255c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 631abe55efSEd Tanous const std::vector<std::string> ¶ms) override 641abe55efSEd Tanous { 658f1ac8e9SGunnar Mills const std::array<const char *, 3> interfaces = { 6662d5e2e4SEd Tanous "xyz.openbmc_project.Inventory.Item.Board", 6762d5e2e4SEd Tanous "xyz.openbmc_project.Inventory.Item.Chassis", 688f1ac8e9SGunnar Mills "xyz.openbmc_project.Inventory.Item.PowerSupply"}; 690f74e643SEd Tanous res.jsonValue["@odata.type"] = "#ChassisCollection.ChassisCollection"; 700f74e643SEd Tanous res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 710f74e643SEd Tanous res.jsonValue["@odata.context"] = 720f74e643SEd Tanous "/redfish/v1/$metadata#ChassisCollection.ChassisCollection"; 730f74e643SEd Tanous res.jsonValue["Name"] = "Chassis Collection"; 740f74e643SEd Tanous 7562d5e2e4SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 7662d5e2e4SEd Tanous crow::connections::systemBus->async_method_call( 7762d5e2e4SEd Tanous [asyncResp](const boost::system::error_code ec, 7862d5e2e4SEd Tanous const std::vector<std::string> &chassisList) { 7962d5e2e4SEd Tanous if (ec) 801abe55efSEd Tanous { 81f12894f8SJason M. Bills messages::internalError(asyncResp->res); 8262d5e2e4SEd Tanous return; 83e37f8451SRapkiewicz, Pawel } 8462d5e2e4SEd Tanous nlohmann::json &chassisArray = 8562d5e2e4SEd Tanous asyncResp->res.jsonValue["Members"]; 8662d5e2e4SEd Tanous chassisArray = nlohmann::json::array(); 8762d5e2e4SEd Tanous for (const std::string &objpath : chassisList) 8862d5e2e4SEd Tanous { 8962d5e2e4SEd Tanous std::size_t lastPos = objpath.rfind("/"); 9062d5e2e4SEd Tanous if (lastPos == std::string::npos) 9162d5e2e4SEd Tanous { 9262d5e2e4SEd Tanous BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath; 9362d5e2e4SEd Tanous continue; 9462d5e2e4SEd Tanous } 9562d5e2e4SEd Tanous chassisArray.push_back( 9662d5e2e4SEd Tanous {{"@odata.id", "/redfish/v1/Chassis/" + 9762d5e2e4SEd Tanous objpath.substr(lastPos + 1)}}); 98e37f8451SRapkiewicz, Pawel } 99e37f8451SRapkiewicz, Pawel 10062d5e2e4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 10162d5e2e4SEd Tanous chassisArray.size(); 10262d5e2e4SEd Tanous }, 10362d5e2e4SEd Tanous "xyz.openbmc_project.ObjectMapper", 10462d5e2e4SEd Tanous "/xyz/openbmc_project/object_mapper", 10562d5e2e4SEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 106734bfe90SGunnar Mills "/xyz/openbmc_project/inventory", int32_t(0), interfaces); 10762d5e2e4SEd Tanous } 108e37f8451SRapkiewicz, Pawel }; 109e37f8451SRapkiewicz, Pawel 110e37f8451SRapkiewicz, Pawel /** 111e37f8451SRapkiewicz, Pawel * Chassis override class for delivering Chassis Schema 112e37f8451SRapkiewicz, Pawel */ 1131abe55efSEd Tanous class Chassis : public Node 1141abe55efSEd Tanous { 115e37f8451SRapkiewicz, Pawel public: 1161abe55efSEd Tanous Chassis(CrowApp &app) : 1171abe55efSEd Tanous Node(app, "/redfish/v1/Chassis/<str>/", std::string()) 1181abe55efSEd Tanous { 119e0d918bcSEd Tanous entityPrivileges = { 120e0d918bcSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 121e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 122e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 123e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 124e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 125e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 126e37f8451SRapkiewicz, Pawel } 127e37f8451SRapkiewicz, Pawel 128e37f8451SRapkiewicz, Pawel private: 129e37f8451SRapkiewicz, Pawel /** 130e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 131e37f8451SRapkiewicz, Pawel */ 13255c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 1331abe55efSEd Tanous const std::vector<std::string> ¶ms) override 1341abe55efSEd Tanous { 135734bfe90SGunnar Mills const std::array<const char *, 3> interfaces = { 136734bfe90SGunnar Mills "xyz.openbmc_project.Inventory.Item.Board", 137734bfe90SGunnar Mills "xyz.openbmc_project.Inventory.Item.Chassis", 138734bfe90SGunnar Mills "xyz.openbmc_project.Inventory.Item.PowerSupply"}; 139734bfe90SGunnar Mills 140e37f8451SRapkiewicz, Pawel // Check if there is required param, truly entering this shall be 141e37f8451SRapkiewicz, Pawel // impossible. 1421abe55efSEd Tanous if (params.size() != 1) 1431abe55efSEd Tanous { 144f12894f8SJason M. Bills messages::internalError(res); 145e37f8451SRapkiewicz, Pawel res.end(); 146e37f8451SRapkiewicz, Pawel return; 147e37f8451SRapkiewicz, Pawel } 148e37f8451SRapkiewicz, Pawel 1490f74e643SEd Tanous res.jsonValue["@odata.type"] = "#Chassis.v1_4_0.Chassis"; 1500f74e643SEd Tanous res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 1510f74e643SEd Tanous res.jsonValue["@odata.context"] = 1520f74e643SEd Tanous "/redfish/v1/$metadata#Chassis.Chassis"; 1530f74e643SEd Tanous res.jsonValue["Name"] = "Chassis Collection"; 1540f74e643SEd Tanous res.jsonValue["ChassisType"] = "RackMount"; 1550f74e643SEd Tanous res.jsonValue["PowerState"] = "On"; 1560f74e643SEd Tanous 15755c7b7a2SEd Tanous const std::string &chassisId = params[0]; 15862d5e2e4SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 15955c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 16062d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 16162d5e2e4SEd Tanous const boost::system::error_code ec, 162daf36e2eSEd Tanous const std::vector<std::pair< 1631abe55efSEd Tanous std::string, std::vector<std::pair< 1641abe55efSEd Tanous std::string, std::vector<std::string>>>>> 165daf36e2eSEd Tanous &subtree) { 16662d5e2e4SEd Tanous if (ec) 1671abe55efSEd Tanous { 168f12894f8SJason M. Bills messages::internalError(asyncResp->res); 169daf36e2eSEd Tanous return; 170daf36e2eSEd Tanous } 171daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 1721abe55efSEd Tanous for (const std::pair< 1731abe55efSEd Tanous std::string, 1741abe55efSEd Tanous std::vector< 1751abe55efSEd Tanous std::pair<std::string, std::vector<std::string>>>> 1761abe55efSEd Tanous &object : subtree) 1771abe55efSEd Tanous { 178daf36e2eSEd Tanous const std::string &path = object.first; 1791abe55efSEd Tanous const std::vector< 1801abe55efSEd Tanous std::pair<std::string, std::vector<std::string>>> 181daf36e2eSEd Tanous &connectionNames = object.second; 182e0d918bcSEd Tanous 1831abe55efSEd Tanous if (!boost::ends_with(path, chassisId)) 1841abe55efSEd Tanous { 185daf36e2eSEd Tanous continue; 186daf36e2eSEd Tanous } 1871abe55efSEd Tanous if (connectionNames.size() < 1) 1881abe55efSEd Tanous { 1891abe55efSEd Tanous BMCWEB_LOG_ERROR << "Only got " 1901abe55efSEd Tanous << connectionNames.size() 19155c7b7a2SEd Tanous << " Connection names"; 192e0d918bcSEd Tanous continue; 193daf36e2eSEd Tanous } 194e0d918bcSEd Tanous 195daf36e2eSEd Tanous const std::string connectionName = connectionNames[0].first; 19655c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 19762d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 19862d5e2e4SEd Tanous const boost::system::error_code ec, 1991abe55efSEd Tanous const std::vector<std::pair< 2001abe55efSEd Tanous std::string, VariantType>> &propertiesList) { 2011abe55efSEd Tanous for (const std::pair<std::string, VariantType> 2021abe55efSEd Tanous &property : propertiesList) 2031abe55efSEd Tanous { 204daf36e2eSEd Tanous const std::string *value = 205abf2add6SEd Tanous std::get_if<std::string>(&property.second); 2061abe55efSEd Tanous if (value != nullptr) 2071abe55efSEd Tanous { 20862d5e2e4SEd Tanous asyncResp->res.jsonValue[property.first] = 20962d5e2e4SEd Tanous *value; 210daf36e2eSEd Tanous } 211daf36e2eSEd Tanous } 21262d5e2e4SEd Tanous asyncResp->res.jsonValue["Name"] = chassisId; 21362d5e2e4SEd Tanous asyncResp->res.jsonValue["Id"] = chassisId; 21462d5e2e4SEd Tanous asyncResp->res.jsonValue["Thermal"] = { 2151abe55efSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 2161abe55efSEd Tanous chassisId + "/Thermal"}}; 2172474adfaSEd Tanous // Power object 2182474adfaSEd Tanous asyncResp->res.jsonValue["Power"] = { 2192474adfaSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 2202474adfaSEd Tanous chassisId + "/Power"}}; 221*029573d4SEd Tanous asyncResp->res.jsonValue["Status"] = { 222*029573d4SEd Tanous {"Health", "OK"}, 223*029573d4SEd Tanous {"State", "Enabled"}, 224*029573d4SEd Tanous }; 2252474adfaSEd Tanous 226*029573d4SEd Tanous asyncResp->res 227*029573d4SEd Tanous .jsonValue["Links"]["ComputerSystems"] = { 228*029573d4SEd Tanous {{"@odata.id", "/redfish/v1/Systems/system"}}}; 229*029573d4SEd Tanous asyncResp->res.jsonValue["Links"]["ManagedBy"] = { 230*029573d4SEd Tanous {{"@odata.id", "/redfish/v1/Managers/bmc"}}}; 231daf36e2eSEd Tanous }, 232daf36e2eSEd Tanous connectionName, path, "org.freedesktop.DBus.Properties", 2331abe55efSEd Tanous "GetAll", 2341abe55efSEd Tanous "xyz.openbmc_project.Inventory.Decorator.Asset"); 235daf36e2eSEd Tanous return; 236daf36e2eSEd Tanous } 237e0d918bcSEd Tanous 238daf36e2eSEd Tanous // Couldn't find an object with that name. return an error 239f12894f8SJason M. Bills messages::resourceNotFound( 240f12894f8SJason M. Bills asyncResp->res, "#Chassis.v1_4_0.Chassis", chassisId); 241daf36e2eSEd Tanous }, 242daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", 243daf36e2eSEd Tanous "/xyz/openbmc_project/object_mapper", 244daf36e2eSEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTree", 245734bfe90SGunnar Mills "/xyz/openbmc_project/inventory", int32_t(0), interfaces); 246e37f8451SRapkiewicz, Pawel } 24762d5e2e4SEd Tanous }; 248e37f8451SRapkiewicz, Pawel } // namespace redfish 249