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 entityPrivileges = { 49 {boost::beast::http::verb::get, {{"Login"}}}, 50 {boost::beast::http::verb::head, {{"Login"}}}, 51 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 52 {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 53 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 54 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 55 } 56 57 private: 58 /** 59 * Functions triggers appropriate requests on DBus 60 */ 61 void doGet(crow::Response &res, const crow::Request &req, 62 const std::vector<std::string> ¶ms) override 63 { 64 const std::array<const char *, 3> interfaces = { 65 "xyz.openbmc_project.Inventory.Item.Board", 66 "xyz.openbmc_project.Inventory.Item.Chassis", 67 "xyz.openbmc_project.Inventory.Item.PowerSupply"}; 68 res.jsonValue["@odata.type"] = "#ChassisCollection.ChassisCollection"; 69 res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 70 res.jsonValue["@odata.context"] = 71 "/redfish/v1/$metadata#ChassisCollection.ChassisCollection"; 72 res.jsonValue["Name"] = "Chassis Collection"; 73 74 auto asyncResp = std::make_shared<AsyncResp>(res); 75 crow::connections::systemBus->async_method_call( 76 [asyncResp](const boost::system::error_code ec, 77 const std::vector<std::string> &chassisList) { 78 if (ec) 79 { 80 messages::internalError(asyncResp->res); 81 return; 82 } 83 nlohmann::json &chassisArray = 84 asyncResp->res.jsonValue["Members"]; 85 chassisArray = nlohmann::json::array(); 86 for (const std::string &objpath : chassisList) 87 { 88 std::size_t lastPos = objpath.rfind("/"); 89 if (lastPos == std::string::npos) 90 { 91 BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath; 92 continue; 93 } 94 chassisArray.push_back( 95 {{"@odata.id", "/redfish/v1/Chassis/" + 96 objpath.substr(lastPos + 1)}}); 97 } 98 99 asyncResp->res.jsonValue["Members@odata.count"] = 100 chassisArray.size(); 101 }, 102 "xyz.openbmc_project.ObjectMapper", 103 "/xyz/openbmc_project/object_mapper", 104 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 105 "/xyz/openbmc_project/inventory", int32_t(0), interfaces); 106 } 107 }; 108 109 /** 110 * Chassis override class for delivering Chassis Schema 111 */ 112 class Chassis : public Node 113 { 114 public: 115 Chassis(CrowApp &app) : 116 Node(app, "/redfish/v1/Chassis/<str>/", std::string()) 117 { 118 entityPrivileges = { 119 {boost::beast::http::verb::get, {{"Login"}}}, 120 {boost::beast::http::verb::head, {{"Login"}}}, 121 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 122 {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 123 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 124 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 125 } 126 127 private: 128 /** 129 * Functions triggers appropriate requests on DBus 130 */ 131 void doGet(crow::Response &res, const crow::Request &req, 132 const std::vector<std::string> ¶ms) override 133 { 134 const std::array<const char *, 3> interfaces = { 135 "xyz.openbmc_project.Inventory.Item.Board", 136 "xyz.openbmc_project.Inventory.Item.Chassis", 137 "xyz.openbmc_project.Inventory.Item.PowerSupply"}; 138 139 // Check if there is required param, truly entering this shall be 140 // impossible. 141 if (params.size() != 1) 142 { 143 messages::internalError(res); 144 res.end(); 145 return; 146 } 147 148 res.jsonValue["@odata.type"] = "#Chassis.v1_4_0.Chassis"; 149 res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 150 res.jsonValue["@odata.context"] = 151 "/redfish/v1/$metadata#Chassis.Chassis"; 152 res.jsonValue["Name"] = "Chassis Collection"; 153 res.jsonValue["ChassisType"] = "RackMount"; 154 res.jsonValue["PowerState"] = "On"; 155 156 const std::string &chassisId = params[0]; 157 auto asyncResp = std::make_shared<AsyncResp>(res); 158 crow::connections::systemBus->async_method_call( 159 [asyncResp, chassisId(std::string(chassisId))]( 160 const boost::system::error_code ec, 161 const std::vector<std::pair< 162 std::string, std::vector<std::pair< 163 std::string, std::vector<std::string>>>>> 164 &subtree) { 165 if (ec) 166 { 167 messages::internalError(asyncResp->res); 168 return; 169 } 170 // Iterate over all retrieved ObjectPaths. 171 for (const std::pair< 172 std::string, 173 std::vector< 174 std::pair<std::string, std::vector<std::string>>>> 175 &object : subtree) 176 { 177 const std::string &path = object.first; 178 const std::vector< 179 std::pair<std::string, std::vector<std::string>>> 180 &connectionNames = object.second; 181 182 if (!boost::ends_with(path, chassisId)) 183 { 184 continue; 185 } 186 if (connectionNames.size() < 1) 187 { 188 BMCWEB_LOG_ERROR << "Only got " 189 << connectionNames.size() 190 << " Connection names"; 191 continue; 192 } 193 194 const std::string connectionName = connectionNames[0].first; 195 crow::connections::systemBus->async_method_call( 196 [asyncResp, chassisId(std::string(chassisId))]( 197 const boost::system::error_code ec, 198 const std::vector<std::pair< 199 std::string, VariantType>> &propertiesList) { 200 for (const std::pair<std::string, VariantType> 201 &property : propertiesList) 202 { 203 const std::string *value = 204 sdbusplus::message::variant_ns::get_if< 205 std::string>(&property.second); 206 if (value != nullptr) 207 { 208 asyncResp->res.jsonValue[property.first] = 209 *value; 210 } 211 } 212 asyncResp->res.jsonValue["Name"] = chassisId; 213 asyncResp->res.jsonValue["Id"] = chassisId; 214 asyncResp->res.jsonValue["Thermal"] = { 215 {"@odata.id", "/redfish/v1/Chassis/" + 216 chassisId + "/Thermal"}}; 217 // Power object 218 asyncResp->res.jsonValue["Power"] = { 219 {"@odata.id", "/redfish/v1/Chassis/" + 220 chassisId + "/Power"}}; 221 222 // TODO: An array of references to computer systems 223 // contained in this chassis. 224 // res.jsonValue["Links"]["ComputerSystems"] 225 // = 226 // {{{"@odata.id", 227 // "/redfish/v1/Systems/1"}}}; 228 // An array of references to the Managers 229 // responsible for managing this chassis. 230 // res.jsonValue["Links"]["ManagedBy"] = 231 // {{{"@odata.id", 232 // "/redfish/v1/Managers/1"}}}; 233 }, 234 connectionName, path, "org.freedesktop.DBus.Properties", 235 "GetAll", 236 "xyz.openbmc_project.Inventory.Decorator.Asset"); 237 return; 238 } 239 240 // Couldn't find an object with that name. return an error 241 messages::resourceNotFound( 242 asyncResp->res, "#Chassis.v1_4_0.Chassis", chassisId); 243 }, 244 "xyz.openbmc_project.ObjectMapper", 245 "/xyz/openbmc_project/object_mapper", 246 "xyz.openbmc_project.ObjectMapper", "GetSubTree", 247 "/xyz/openbmc_project/inventory", int32_t(0), interfaces); 248 } 249 }; 250 } // namespace redfish 251