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 { 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 { 7062d5e2e4SEd Tanous const std::array<const char *, 4> interfaces = { 7162d5e2e4SEd Tanous "xyz.openbmc_project.Inventory.Item.Board", 7262d5e2e4SEd Tanous "xyz.openbmc_project.Inventory.Item.Chassis", 7362d5e2e4SEd Tanous "xyz.openbmc_project.Inventory.Item.PowerSupply", 7462d5e2e4SEd Tanous "xyz.openbmc_project.Inventory.Item.System", 7562d5e2e4SEd Tanous }; 7655c7b7a2SEd Tanous res.jsonValue = Node::json; 7762d5e2e4SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 7862d5e2e4SEd Tanous crow::connections::systemBus->async_method_call( 7962d5e2e4SEd Tanous [asyncResp](const boost::system::error_code ec, 8062d5e2e4SEd Tanous const std::vector<std::string> &chassisList) { 8162d5e2e4SEd Tanous if (ec) 821abe55efSEd Tanous { 83f12894f8SJason M. Bills messages::internalError(asyncResp->res); 8462d5e2e4SEd Tanous return; 85e37f8451SRapkiewicz, Pawel } 8662d5e2e4SEd Tanous nlohmann::json &chassisArray = 8762d5e2e4SEd Tanous asyncResp->res.jsonValue["Members"]; 8862d5e2e4SEd Tanous chassisArray = nlohmann::json::array(); 8962d5e2e4SEd Tanous for (const std::string &objpath : chassisList) 9062d5e2e4SEd Tanous { 9162d5e2e4SEd Tanous std::size_t lastPos = objpath.rfind("/"); 9262d5e2e4SEd Tanous if (lastPos == std::string::npos) 9362d5e2e4SEd Tanous { 9462d5e2e4SEd Tanous BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath; 9562d5e2e4SEd Tanous continue; 9662d5e2e4SEd Tanous } 9762d5e2e4SEd Tanous chassisArray.push_back( 9862d5e2e4SEd Tanous {{"@odata.id", "/redfish/v1/Chassis/" + 9962d5e2e4SEd Tanous objpath.substr(lastPos + 1)}}); 100e37f8451SRapkiewicz, Pawel } 101e37f8451SRapkiewicz, Pawel 10262d5e2e4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 10362d5e2e4SEd Tanous chassisArray.size(); 10462d5e2e4SEd Tanous }, 10562d5e2e4SEd Tanous "xyz.openbmc_project.ObjectMapper", 10662d5e2e4SEd Tanous "/xyz/openbmc_project/object_mapper", 10762d5e2e4SEd Tanous "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 10862d5e2e4SEd Tanous "/xyz/openbmc_project/inventory", int32_t(3), interfaces); 10962d5e2e4SEd Tanous } 110e37f8451SRapkiewicz, Pawel }; 111e37f8451SRapkiewicz, Pawel 112e37f8451SRapkiewicz, Pawel /** 113e37f8451SRapkiewicz, Pawel * Chassis override class for delivering Chassis Schema 114e37f8451SRapkiewicz, Pawel */ 1151abe55efSEd Tanous class Chassis : public Node 1161abe55efSEd Tanous { 117e37f8451SRapkiewicz, Pawel public: 1181abe55efSEd Tanous Chassis(CrowApp &app) : 1191abe55efSEd Tanous Node(app, "/redfish/v1/Chassis/<str>/", std::string()) 1201abe55efSEd Tanous { 121e37f8451SRapkiewicz, Pawel Node::json["@odata.type"] = "#Chassis.v1_4_0.Chassis"; 122e37f8451SRapkiewicz, Pawel Node::json["@odata.id"] = "/redfish/v1/Chassis"; 123e37f8451SRapkiewicz, Pawel Node::json["@odata.context"] = "/redfish/v1/$metadata#Chassis.Chassis"; 124e37f8451SRapkiewicz, Pawel Node::json["Name"] = "Chassis Collection"; 1256c233015SEd Tanous Node::json["ChassisType"] = "RackMount"; 126aef72909SEd Tanous Node::json["PowerState"] = "On"; 127e37f8451SRapkiewicz, Pawel 128e0d918bcSEd Tanous entityPrivileges = { 129e0d918bcSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 130e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 131e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 132e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 133e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 134e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 135e37f8451SRapkiewicz, Pawel } 136e37f8451SRapkiewicz, Pawel 137e37f8451SRapkiewicz, Pawel private: 138e37f8451SRapkiewicz, Pawel /** 139e37f8451SRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 140e37f8451SRapkiewicz, Pawel */ 14155c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 1421abe55efSEd Tanous const std::vector<std::string> ¶ms) override 1431abe55efSEd Tanous { 144e37f8451SRapkiewicz, Pawel // Check if there is required param, truly entering this shall be 145e37f8451SRapkiewicz, Pawel // impossible. 1461abe55efSEd Tanous if (params.size() != 1) 1471abe55efSEd Tanous { 148f12894f8SJason M. Bills messages::internalError(res); 149e37f8451SRapkiewicz, Pawel res.end(); 150e37f8451SRapkiewicz, Pawel return; 151e37f8451SRapkiewicz, Pawel } 152e37f8451SRapkiewicz, Pawel 15355c7b7a2SEd Tanous res.jsonValue = Node::json; 15455c7b7a2SEd Tanous const std::string &chassisId = params[0]; 15562d5e2e4SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 15655c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 15762d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 15862d5e2e4SEd Tanous const boost::system::error_code ec, 159daf36e2eSEd Tanous const std::vector<std::pair< 1601abe55efSEd Tanous std::string, std::vector<std::pair< 1611abe55efSEd Tanous std::string, std::vector<std::string>>>>> 162daf36e2eSEd Tanous &subtree) { 16362d5e2e4SEd Tanous if (ec) 1641abe55efSEd Tanous { 165f12894f8SJason M. Bills messages::internalError(asyncResp->res); 166daf36e2eSEd Tanous return; 167daf36e2eSEd Tanous } 168daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 1691abe55efSEd Tanous for (const std::pair< 1701abe55efSEd Tanous std::string, 1711abe55efSEd Tanous std::vector< 1721abe55efSEd Tanous std::pair<std::string, std::vector<std::string>>>> 1731abe55efSEd Tanous &object : subtree) 1741abe55efSEd Tanous { 175daf36e2eSEd Tanous const std::string &path = object.first; 1761abe55efSEd Tanous const std::vector< 1771abe55efSEd Tanous std::pair<std::string, std::vector<std::string>>> 178daf36e2eSEd Tanous &connectionNames = object.second; 179e0d918bcSEd Tanous 1801abe55efSEd Tanous if (!boost::ends_with(path, chassisId)) 1811abe55efSEd Tanous { 182daf36e2eSEd Tanous continue; 183daf36e2eSEd Tanous } 1841abe55efSEd Tanous if (connectionNames.size() < 1) 1851abe55efSEd Tanous { 1861abe55efSEd Tanous BMCWEB_LOG_ERROR << "Only got " 1871abe55efSEd Tanous << connectionNames.size() 18855c7b7a2SEd Tanous << " Connection names"; 189e0d918bcSEd Tanous continue; 190daf36e2eSEd Tanous } 191e0d918bcSEd Tanous 192daf36e2eSEd Tanous const std::string connectionName = connectionNames[0].first; 19355c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 19462d5e2e4SEd Tanous [asyncResp, chassisId(std::string(chassisId))]( 19562d5e2e4SEd Tanous const boost::system::error_code ec, 1961abe55efSEd Tanous const std::vector<std::pair< 1971abe55efSEd Tanous std::string, VariantType>> &propertiesList) { 1981abe55efSEd Tanous for (const std::pair<std::string, VariantType> 1991abe55efSEd Tanous &property : propertiesList) 2001abe55efSEd Tanous { 201daf36e2eSEd Tanous const std::string *value = 2021abe55efSEd Tanous mapbox::getPtr<const std::string>( 2031abe55efSEd Tanous property.second); 2041abe55efSEd Tanous if (value != nullptr) 2051abe55efSEd Tanous { 20662d5e2e4SEd Tanous asyncResp->res.jsonValue[property.first] = 20762d5e2e4SEd Tanous *value; 208daf36e2eSEd Tanous } 209daf36e2eSEd Tanous } 21062d5e2e4SEd Tanous asyncResp->res.jsonValue["Name"] = chassisId; 21162d5e2e4SEd Tanous asyncResp->res.jsonValue["Id"] = chassisId; 21262d5e2e4SEd Tanous asyncResp->res.jsonValue["Thermal"] = { 2131abe55efSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 2141abe55efSEd Tanous chassisId + "/Thermal"}}; 215*2474adfaSEd Tanous // Power object 216*2474adfaSEd Tanous asyncResp->res.jsonValue["Power"] = { 217*2474adfaSEd Tanous {"@odata.id", "/redfish/v1/Chassis/" + 218*2474adfaSEd Tanous chassisId + "/Power"}}; 219*2474adfaSEd Tanous 220*2474adfaSEd Tanous // TODO: An array of references to computer systems 221*2474adfaSEd Tanous // contained in this chassis. 222*2474adfaSEd Tanous // res.jsonValue["Links"]["ComputerSystems"] 223*2474adfaSEd Tanous // = 224*2474adfaSEd Tanous // {{{"@odata.id", 225*2474adfaSEd Tanous // "/redfish/v1/Systems/1"}}}; 226*2474adfaSEd Tanous // An array of references to the Managers 227*2474adfaSEd Tanous // responsible for managing this chassis. 228*2474adfaSEd Tanous // res.jsonValue["Links"]["ManagedBy"] = 229*2474adfaSEd Tanous // {{{"@odata.id", 230*2474adfaSEd Tanous // "/redfish/v1/Managers/1"}}}; 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", 245daf36e2eSEd Tanous "/xyz/openbmc_project/inventory", int32_t(0), 246daf36e2eSEd Tanous std::array<const char *, 1>{ 247daf36e2eSEd Tanous "xyz.openbmc_project.Inventory.Decorator.Asset"}); 248e37f8451SRapkiewicz, Pawel } 24962d5e2e4SEd Tanous }; 250e37f8451SRapkiewicz, Pawel } // namespace redfish 251