1 /* 2 // Copyright (c) 2018 Intel Corporation 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 */ 16 #pragma once 17 18 #include "node.hpp" 19 20 #include <boost/container/flat_map.hpp> 21 22 namespace redfish 23 { 24 25 /** 26 * DBus types primitives for several generic DBus interfaces 27 * TODO(Pawel) consider move this to separate file into boost::dbus 28 */ 29 // Note, this is not a very useful Variant, but because it isn't used to get 30 // values, it should be as simple as possible 31 // TODO(ed) invent a nullvariant type 32 using VariantType = sdbusplus::message::variant<bool, std::string, uint64_t>; 33 using ManagedObjectsType = std::vector<std::pair< 34 sdbusplus::message::object_path, 35 std::vector<std::pair<std::string, 36 std::vector<std::pair<std::string, VariantType>>>>>>; 37 38 using PropertiesType = boost::container::flat_map<std::string, VariantType>; 39 40 /** 41 * ChassisCollection derived class for delivering Chassis Collection Schema 42 */ 43 class ChassisCollection : public Node 44 { 45 public: 46 ChassisCollection(CrowApp &app) : Node(app, "/redfish/v1/Chassis/") 47 { 48 Node::json["@odata.type"] = "#ChassisCollection.ChassisCollection"; 49 Node::json["@odata.id"] = "/redfish/v1/Chassis"; 50 Node::json["@odata.context"] = 51 "/redfish/v1/$metadata#ChassisCollection.ChassisCollection"; 52 Node::json["Name"] = "Chassis Collection"; 53 54 entityPrivileges = { 55 {boost::beast::http::verb::get, {{"Login"}}}, 56 {boost::beast::http::verb::head, {{"Login"}}}, 57 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 58 {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 59 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 60 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 61 } 62 63 private: 64 /** 65 * Functions triggers appropriate requests on DBus 66 */ 67 void doGet(crow::Response &res, const crow::Request &req, 68 const std::vector<std::string> ¶ms) override 69 { 70 const std::array<const char *, 4> interfaces = { 71 "xyz.openbmc_project.Inventory.Item.Board", 72 "xyz.openbmc_project.Inventory.Item.Chassis", 73 "xyz.openbmc_project.Inventory.Item.PowerSupply", 74 "xyz.openbmc_project.Inventory.Item.System", 75 }; 76 res.jsonValue = Node::json; 77 auto asyncResp = std::make_shared<AsyncResp>(res); 78 crow::connections::systemBus->async_method_call( 79 [asyncResp](const boost::system::error_code ec, 80 const std::vector<std::string> &chassisList) { 81 if (ec) 82 { 83 messages::internalError(asyncResp->res); 84 return; 85 } 86 nlohmann::json &chassisArray = 87 asyncResp->res.jsonValue["Members"]; 88 chassisArray = nlohmann::json::array(); 89 for (const std::string &objpath : chassisList) 90 { 91 std::size_t lastPos = objpath.rfind("/"); 92 if (lastPos == std::string::npos) 93 { 94 BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath; 95 continue; 96 } 97 chassisArray.push_back( 98 {{"@odata.id", "/redfish/v1/Chassis/" + 99 objpath.substr(lastPos + 1)}}); 100 } 101 102 asyncResp->res.jsonValue["Members@odata.count"] = 103 chassisArray.size(); 104 }, 105 "xyz.openbmc_project.ObjectMapper", 106 "/xyz/openbmc_project/object_mapper", 107 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 108 "/xyz/openbmc_project/inventory", int32_t(3), interfaces); 109 } 110 }; 111 112 /** 113 * Chassis override class for delivering Chassis Schema 114 */ 115 class Chassis : public Node 116 { 117 public: 118 Chassis(CrowApp &app) : 119 Node(app, "/redfish/v1/Chassis/<str>/", std::string()) 120 { 121 Node::json["@odata.type"] = "#Chassis.v1_4_0.Chassis"; 122 Node::json["@odata.id"] = "/redfish/v1/Chassis"; 123 Node::json["@odata.context"] = "/redfish/v1/$metadata#Chassis.Chassis"; 124 Node::json["Name"] = "Chassis Collection"; 125 Node::json["ChassisType"] = "RackMount"; 126 Node::json["PowerState"] = "On"; 127 128 entityPrivileges = { 129 {boost::beast::http::verb::get, {{"Login"}}}, 130 {boost::beast::http::verb::head, {{"Login"}}}, 131 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 132 {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 133 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 134 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 135 } 136 137 private: 138 /** 139 * Functions triggers appropriate requests on DBus 140 */ 141 void doGet(crow::Response &res, const crow::Request &req, 142 const std::vector<std::string> ¶ms) override 143 { 144 // Check if there is required param, truly entering this shall be 145 // impossible. 146 if (params.size() != 1) 147 { 148 messages::internalError(res); 149 res.end(); 150 return; 151 } 152 153 res.jsonValue = Node::json; 154 const std::string &chassisId = params[0]; 155 auto asyncResp = std::make_shared<AsyncResp>(res); 156 crow::connections::systemBus->async_method_call( 157 [asyncResp, chassisId(std::string(chassisId))]( 158 const boost::system::error_code ec, 159 const std::vector<std::pair< 160 std::string, std::vector<std::pair< 161 std::string, std::vector<std::string>>>>> 162 &subtree) { 163 if (ec) 164 { 165 messages::internalError(asyncResp->res); 166 return; 167 } 168 // Iterate over all retrieved ObjectPaths. 169 for (const std::pair< 170 std::string, 171 std::vector< 172 std::pair<std::string, std::vector<std::string>>>> 173 &object : subtree) 174 { 175 const std::string &path = object.first; 176 const std::vector< 177 std::pair<std::string, std::vector<std::string>>> 178 &connectionNames = object.second; 179 180 if (!boost::ends_with(path, chassisId)) 181 { 182 continue; 183 } 184 if (connectionNames.size() < 1) 185 { 186 BMCWEB_LOG_ERROR << "Only got " 187 << connectionNames.size() 188 << " Connection names"; 189 continue; 190 } 191 192 const std::string connectionName = connectionNames[0].first; 193 crow::connections::systemBus->async_method_call( 194 [asyncResp, chassisId(std::string(chassisId))]( 195 const boost::system::error_code ec, 196 const std::vector<std::pair< 197 std::string, VariantType>> &propertiesList) { 198 for (const std::pair<std::string, VariantType> 199 &property : propertiesList) 200 { 201 const std::string *value = 202 mapbox::getPtr<const std::string>( 203 property.second); 204 if (value != nullptr) 205 { 206 asyncResp->res.jsonValue[property.first] = 207 *value; 208 } 209 } 210 asyncResp->res.jsonValue["Name"] = chassisId; 211 asyncResp->res.jsonValue["Id"] = chassisId; 212 asyncResp->res.jsonValue["Thermal"] = { 213 {"@odata.id", "/redfish/v1/Chassis/" + 214 chassisId + "/Thermal"}}; 215 // Power object 216 asyncResp->res.jsonValue["Power"] = { 217 {"@odata.id", "/redfish/v1/Chassis/" + 218 chassisId + "/Power"}}; 219 220 // TODO: An array of references to computer systems 221 // contained in this chassis. 222 // res.jsonValue["Links"]["ComputerSystems"] 223 // = 224 // {{{"@odata.id", 225 // "/redfish/v1/Systems/1"}}}; 226 // An array of references to the Managers 227 // responsible for managing this chassis. 228 // res.jsonValue["Links"]["ManagedBy"] = 229 // {{{"@odata.id", 230 // "/redfish/v1/Managers/1"}}}; 231 }, 232 connectionName, path, "org.freedesktop.DBus.Properties", 233 "GetAll", 234 "xyz.openbmc_project.Inventory.Decorator.Asset"); 235 return; 236 } 237 238 // Couldn't find an object with that name. return an error 239 messages::resourceNotFound( 240 asyncResp->res, "#Chassis.v1_4_0.Chassis", chassisId); 241 }, 242 "xyz.openbmc_project.ObjectMapper", 243 "/xyz/openbmc_project/object_mapper", 244 "xyz.openbmc_project.ObjectMapper", "GetSubTree", 245 "/xyz/openbmc_project/inventory", int32_t(0), 246 std::array<const char *, 1>{ 247 "xyz.openbmc_project.Inventory.Decorator.Asset"}); 248 } 249 }; 250 } // namespace redfish 251