1729dae72SJennifer Lee /* 2729dae72SJennifer Lee // Copyright (c) 2018 Intel Corporation 3729dae72SJennifer Lee // 4729dae72SJennifer Lee // Licensed under the Apache License, Version 2.0 (the "License"); 5729dae72SJennifer Lee // you may not use this file except in compliance with the License. 6729dae72SJennifer Lee // You may obtain a copy of the License at 7729dae72SJennifer Lee // 8729dae72SJennifer Lee // http://www.apache.org/licenses/LICENSE-2.0 9729dae72SJennifer Lee // 10729dae72SJennifer Lee // Unless required by applicable law or agreed to in writing, software 11729dae72SJennifer Lee // distributed under the License is distributed on an "AS IS" BASIS, 12729dae72SJennifer Lee // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13729dae72SJennifer Lee // See the License for the specific language governing permissions and 14729dae72SJennifer Lee // limitations under the License. 15729dae72SJennifer Lee */ 16729dae72SJennifer Lee #pragma once 17729dae72SJennifer Lee 18729dae72SJennifer Lee #include "node.hpp" 19729dae72SJennifer Lee #include <boost/container/flat_map.hpp> 20729dae72SJennifer Lee 21729dae72SJennifer Lee namespace redfish { 22*acb7cfb4SJennifer Lee static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateMatcher; 23729dae72SJennifer Lee 24729dae72SJennifer Lee class OnDemandSoftwareInventoryProvider { 25729dae72SJennifer Lee public: 26729dae72SJennifer Lee template <typename CallbackFunc> 27*acb7cfb4SJennifer Lee void getAllSoftwareInventoryObject(CallbackFunc &&callback) { 2855c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 29729dae72SJennifer Lee [callback{std::move(callback)}]( 30729dae72SJennifer Lee const boost::system::error_code error_code, 31729dae72SJennifer Lee const std::vector<std::pair< 32729dae72SJennifer Lee std::string, 33729dae72SJennifer Lee std::vector<std::pair<std::string, std::vector<std::string>>>>> 34729dae72SJennifer Lee &subtree) { 3555c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "get all software inventory object callback..."; 36729dae72SJennifer Lee if (error_code) { 37729dae72SJennifer Lee // Something wrong on DBus, the error_code is not important at this 38729dae72SJennifer Lee // moment, just return success=false, and empty output. Since size 39729dae72SJennifer Lee // of vector may vary depending on information from Entity Manager, 40729dae72SJennifer Lee // and empty output could not be treated same way as error. 416c4eb9deSJennifer Lee callback(false, subtree); 42729dae72SJennifer Lee return; 43729dae72SJennifer Lee } 44729dae72SJennifer Lee 456c4eb9deSJennifer Lee if (subtree.empty()) { 4655c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "subtree empty"; 476c4eb9deSJennifer Lee callback(false, subtree); 486c4eb9deSJennifer Lee } else { 4955c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "subtree has something"; 506c4eb9deSJennifer Lee callback(true, subtree); 51729dae72SJennifer Lee } 52729dae72SJennifer Lee }, 53729dae72SJennifer Lee "xyz.openbmc_project.ObjectMapper", 54729dae72SJennifer Lee "/xyz/openbmc_project/object_mapper", 556c4eb9deSJennifer Lee "xyz.openbmc_project.ObjectMapper", "GetSubTree", 566c4eb9deSJennifer Lee "/xyz/openbmc_project/software", int32_t(1), 57*acb7cfb4SJennifer Lee std::array<const char *, 1>{"xyz.openbmc_project.Software.Activation"}); 58729dae72SJennifer Lee } 59729dae72SJennifer Lee }; 60729dae72SJennifer Lee 61729dae72SJennifer Lee class UpdateService : public Node { 62729dae72SJennifer Lee public: 63729dae72SJennifer Lee UpdateService(CrowApp &app) : Node(app, "/redfish/v1/UpdateService/") { 64729dae72SJennifer Lee Node::json["@odata.type"] = "#UpdateService.v1_2_0.UpdateService"; 65729dae72SJennifer Lee Node::json["@odata.id"] = "/redfish/v1/UpdateService"; 66729dae72SJennifer Lee Node::json["@odata.context"] = 67729dae72SJennifer Lee "/redfish/v1/$metadata#UpdateService.UpdateService"; 68729dae72SJennifer Lee Node::json["Id"] = "UpdateService"; 69729dae72SJennifer Lee Node::json["Description"] = "Service for Software Update"; 70729dae72SJennifer Lee Node::json["Name"] = "Update Service"; 71*acb7cfb4SJennifer Lee Node::json["HttpPushUri"] = "/redfish/v1/UpdateService"; 72729dae72SJennifer Lee Node::json["ServiceEnabled"] = true; // UpdateService cannot be disabled 736c4eb9deSJennifer Lee Node::json["FirmwareInventory"] = { 746c4eb9deSJennifer Lee {"@odata.id", "/redfish/v1/UpdateService/FirmwareInventory"}}; 75729dae72SJennifer Lee 76729dae72SJennifer Lee entityPrivileges = { 77729dae72SJennifer Lee {boost::beast::http::verb::get, {{"Login"}}}, 78729dae72SJennifer Lee {boost::beast::http::verb::head, {{"Login"}}}, 79729dae72SJennifer Lee {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 80729dae72SJennifer Lee {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 81729dae72SJennifer Lee {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 82729dae72SJennifer Lee {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 83729dae72SJennifer Lee } 84729dae72SJennifer Lee 85729dae72SJennifer Lee private: 8655c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 87729dae72SJennifer Lee const std::vector<std::string> ¶ms) override { 8855c7b7a2SEd Tanous res.jsonValue = Node::json; 89729dae72SJennifer Lee res.end(); 90729dae72SJennifer Lee } 91*acb7cfb4SJennifer Lee static void activateImage(const std::string &obj_path) { 92*acb7cfb4SJennifer Lee crow::connections::systemBus->async_method_call( 93*acb7cfb4SJennifer Lee [obj_path](const boost::system::error_code error_code) { 94*acb7cfb4SJennifer Lee if (error_code) { 95*acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "error_code = " << error_code; 96*acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "error msg = " << error_code.message(); 97*acb7cfb4SJennifer Lee } 98*acb7cfb4SJennifer Lee }, 99*acb7cfb4SJennifer Lee "xyz.openbmc_project.Software.BMC.Updater", obj_path, 100*acb7cfb4SJennifer Lee "org.freedesktop.DBus.Properties", "Set", 101*acb7cfb4SJennifer Lee "xyz.openbmc_project.Software.Activation", "RequestedActivation", 102*acb7cfb4SJennifer Lee sdbusplus::message::variant<std::string>( 103*acb7cfb4SJennifer Lee "xyz.openbmc_project.Software.Activation.RequestedActivations." 104*acb7cfb4SJennifer Lee "Active")); 105*acb7cfb4SJennifer Lee } 106*acb7cfb4SJennifer Lee void doPost(crow::Response &res, const crow::Request &req, 107*acb7cfb4SJennifer Lee const std::vector<std::string> ¶ms) override { 108*acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "doPost..."; 109*acb7cfb4SJennifer Lee 110*acb7cfb4SJennifer Lee // Only allow one FW update at a time 111*acb7cfb4SJennifer Lee if (fwUpdateMatcher != nullptr) { 112*acb7cfb4SJennifer Lee res.addHeader("Retry-After", "30"); 113*acb7cfb4SJennifer Lee res.result(boost::beast::http::status::service_unavailable); 114*acb7cfb4SJennifer Lee res.jsonValue = messages::serviceTemporarilyUnavailable("3"); 115*acb7cfb4SJennifer Lee res.end(); 116*acb7cfb4SJennifer Lee return; 117*acb7cfb4SJennifer Lee } 118*acb7cfb4SJennifer Lee // Make this const static so it survives outside this method 119*acb7cfb4SJennifer Lee static boost::asio::deadline_timer timeout(*req.ioService, 120*acb7cfb4SJennifer Lee boost::posix_time::seconds(5)); 121*acb7cfb4SJennifer Lee 122*acb7cfb4SJennifer Lee timeout.expires_from_now(boost::posix_time::seconds(5)); 123*acb7cfb4SJennifer Lee 124*acb7cfb4SJennifer Lee timeout.async_wait([&res](const boost::system::error_code &ec) { 125*acb7cfb4SJennifer Lee fwUpdateMatcher = nullptr; 126*acb7cfb4SJennifer Lee if (ec == boost::asio::error::operation_aborted) { 127*acb7cfb4SJennifer Lee // expected, we were canceled before the timer completed. 128*acb7cfb4SJennifer Lee return; 129*acb7cfb4SJennifer Lee } 130*acb7cfb4SJennifer Lee BMCWEB_LOG_ERROR << "Timed out waiting for firmware object being created"; 131*acb7cfb4SJennifer Lee BMCWEB_LOG_ERROR << "FW image may has already been uploaded to server"; 132*acb7cfb4SJennifer Lee if (ec) { 133*acb7cfb4SJennifer Lee BMCWEB_LOG_ERROR << "Async_wait failed" << ec; 134*acb7cfb4SJennifer Lee return; 135*acb7cfb4SJennifer Lee } 136*acb7cfb4SJennifer Lee 137*acb7cfb4SJennifer Lee res.result(boost::beast::http::status::internal_server_error); 138*acb7cfb4SJennifer Lee res.jsonValue = redfish::messages::internalError(); 139*acb7cfb4SJennifer Lee res.end(); 140*acb7cfb4SJennifer Lee }); 141*acb7cfb4SJennifer Lee 142*acb7cfb4SJennifer Lee auto callback = [&res](sdbusplus::message::message &m) { 143*acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "Match fired"; 144*acb7cfb4SJennifer Lee bool flag = false; 145*acb7cfb4SJennifer Lee 146*acb7cfb4SJennifer Lee if (m.is_method_error()) { 147*acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "Dbus method error!!!"; 148*acb7cfb4SJennifer Lee res.end(); 149*acb7cfb4SJennifer Lee return; 150*acb7cfb4SJennifer Lee } 151*acb7cfb4SJennifer Lee std::vector<std::pair< 152*acb7cfb4SJennifer Lee std::string, 153*acb7cfb4SJennifer Lee std::vector<std::pair<std::string, 154*acb7cfb4SJennifer Lee sdbusplus::message::variant<std::string>>>>> 155*acb7cfb4SJennifer Lee interfaces_properties; 156*acb7cfb4SJennifer Lee 157*acb7cfb4SJennifer Lee sdbusplus::message::object_path obj_path; 158*acb7cfb4SJennifer Lee 159*acb7cfb4SJennifer Lee m.read(obj_path, interfaces_properties); // Read in the object path 160*acb7cfb4SJennifer Lee // that was just created 161*acb7cfb4SJennifer Lee // std::string str_objpath = obj_path.str; // keep a copy for 162*acb7cfb4SJennifer Lee // constructing response message 163*acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "obj path = " << obj_path.str; // str_objpath; 164*acb7cfb4SJennifer Lee for (auto &interface : interfaces_properties) { 165*acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "interface = " << interface.first; 166*acb7cfb4SJennifer Lee 167*acb7cfb4SJennifer Lee if (interface.first == "xyz.openbmc_project.Software.Activation") { 168*acb7cfb4SJennifer Lee // cancel timer only when xyz.openbmc_project.Software.Activation 169*acb7cfb4SJennifer Lee // interface is added 170*acb7cfb4SJennifer Lee boost::system::error_code ec; 171*acb7cfb4SJennifer Lee timeout.cancel(ec); 172*acb7cfb4SJennifer Lee if (ec) { 173*acb7cfb4SJennifer Lee BMCWEB_LOG_ERROR << "error canceling timer " << ec; 174*acb7cfb4SJennifer Lee } 175*acb7cfb4SJennifer Lee UpdateService::activateImage(obj_path.str); // str_objpath); 176*acb7cfb4SJennifer Lee res.jsonValue = redfish::messages::success(); 177*acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "ending response"; 178*acb7cfb4SJennifer Lee res.end(); 179*acb7cfb4SJennifer Lee fwUpdateMatcher = nullptr; 180*acb7cfb4SJennifer Lee } 181*acb7cfb4SJennifer Lee } 182*acb7cfb4SJennifer Lee }; 183*acb7cfb4SJennifer Lee 184*acb7cfb4SJennifer Lee fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>( 185*acb7cfb4SJennifer Lee *crow::connections::systemBus, 186*acb7cfb4SJennifer Lee "interface='org.freedesktop.DBus.ObjectManager',type='signal'," 187*acb7cfb4SJennifer Lee "member='InterfacesAdded',path='/xyz/openbmc_project/software'", 188*acb7cfb4SJennifer Lee callback); 189*acb7cfb4SJennifer Lee 190*acb7cfb4SJennifer Lee std::string filepath( 191*acb7cfb4SJennifer Lee "/tmp/images/" + 192*acb7cfb4SJennifer Lee boost::uuids::to_string(boost::uuids::random_generator()())); 193*acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "Writing file to " << filepath; 194*acb7cfb4SJennifer Lee std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary | 195*acb7cfb4SJennifer Lee std::ofstream::trunc); 196*acb7cfb4SJennifer Lee out << req.body; 197*acb7cfb4SJennifer Lee out.close(); 198*acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "file upload complete!!"; 199*acb7cfb4SJennifer Lee } 200729dae72SJennifer Lee }; 201729dae72SJennifer Lee 202729dae72SJennifer Lee class SoftwareInventoryCollection : public Node { 203729dae72SJennifer Lee public: 204729dae72SJennifer Lee /* 205729dae72SJennifer Lee * Default Constructor 206729dae72SJennifer Lee */ 207729dae72SJennifer Lee template <typename CrowApp> 208729dae72SJennifer Lee SoftwareInventoryCollection(CrowApp &app) 2096c4eb9deSJennifer Lee : Node(app, "/redfish/v1/UpdateService/FirmwareInventory/") { 210729dae72SJennifer Lee Node::json["@odata.type"] = 211729dae72SJennifer Lee "#SoftwareInventoryCollection.SoftwareInventoryCollection"; 2126c4eb9deSJennifer Lee Node::json["@odata.id"] = "/redfish/v1/UpdateService/FirmwareInventory"; 213729dae72SJennifer Lee Node::json["@odata.context"] = 214729dae72SJennifer Lee "/redfish/v1/" 215729dae72SJennifer Lee "$metadata#SoftwareInventoryCollection.SoftwareInventoryCollection"; 216729dae72SJennifer Lee Node::json["Name"] = "Software Inventory Collection"; 217729dae72SJennifer Lee 218729dae72SJennifer Lee entityPrivileges = { 219729dae72SJennifer Lee {boost::beast::http::verb::get, {{"Login"}}}, 220729dae72SJennifer Lee {boost::beast::http::verb::head, {{"Login"}}}, 221729dae72SJennifer Lee {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 222729dae72SJennifer Lee {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 223729dae72SJennifer Lee {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 224729dae72SJennifer Lee {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 225729dae72SJennifer Lee } 226729dae72SJennifer Lee 227729dae72SJennifer Lee private: 228729dae72SJennifer Lee /** 229729dae72SJennifer Lee * Functions triggers appropriate requests on DBus 230729dae72SJennifer Lee */ 23155c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 232729dae72SJennifer Lee const std::vector<std::string> ¶ms) override { 23355c7b7a2SEd Tanous res.jsonValue = Node::json; 234*acb7cfb4SJennifer Lee softwareInventoryProvider.getAllSoftwareInventoryObject( 2356c4eb9deSJennifer Lee [&](const bool &success, 2366c4eb9deSJennifer Lee const std::vector<std::pair< 2376c4eb9deSJennifer Lee std::string, 2386c4eb9deSJennifer Lee std::vector<std::pair<std::string, std::vector<std::string>>>>> 2396c4eb9deSJennifer Lee &subtree) { 2406c4eb9deSJennifer Lee if (!success) { 241729dae72SJennifer Lee res.result(boost::beast::http::status::internal_server_error); 242*acb7cfb4SJennifer Lee res.jsonValue = messages::internalError(); 2436c4eb9deSJennifer Lee res.end(); 2446c4eb9deSJennifer Lee return; 245729dae72SJennifer Lee } 2466c4eb9deSJennifer Lee 2476c4eb9deSJennifer Lee if (subtree.empty()) { 24855c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "subtree empty!!"; 249*acb7cfb4SJennifer Lee res.result(boost::beast::http::status::internal_server_error); 250*acb7cfb4SJennifer Lee res.jsonValue = messages::internalError(); 251729dae72SJennifer Lee res.end(); 2526c4eb9deSJennifer Lee return; 2536c4eb9deSJennifer Lee } 2546c4eb9deSJennifer Lee 25555c7b7a2SEd Tanous res.jsonValue["Members"] = nlohmann::json::array(); 256*acb7cfb4SJennifer Lee res.jsonValue["Members@odata.count"] = 0; 257*acb7cfb4SJennifer Lee 258*acb7cfb4SJennifer Lee std::shared_ptr<AsyncResp> asyncResp = 259*acb7cfb4SJennifer Lee std::make_shared<AsyncResp>(res); 2606c4eb9deSJennifer Lee 2616c4eb9deSJennifer Lee for (auto &obj : subtree) { 2626c4eb9deSJennifer Lee const std::vector<std::pair<std::string, std::vector<std::string>>> 2636c4eb9deSJennifer Lee &connections = obj.second; 2646c4eb9deSJennifer Lee 265*acb7cfb4SJennifer Lee // if can't parse fw id then return 266*acb7cfb4SJennifer Lee std::size_t id_pos; 267*acb7cfb4SJennifer Lee if ((id_pos = obj.first.rfind("/")) == std::string::npos) { 268*acb7cfb4SJennifer Lee res.result(boost::beast::http::status::internal_server_error); 269*acb7cfb4SJennifer Lee res.jsonValue = messages::internalError(); 270*acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "Can't parse firmware ID!!"; 271*acb7cfb4SJennifer Lee res.end(); 272*acb7cfb4SJennifer Lee return; 273*acb7cfb4SJennifer Lee } 274*acb7cfb4SJennifer Lee std::string fw_id = obj.first.substr(id_pos + 1); 275*acb7cfb4SJennifer Lee 276*acb7cfb4SJennifer Lee for (const auto &conn : connections) { 2776c4eb9deSJennifer Lee const std::string connectionName = conn.first; 27855c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "connectionName = " << connectionName; 27955c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "obj.first = " << obj.first; 2806c4eb9deSJennifer Lee 28155c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 282*acb7cfb4SJennifer Lee [asyncResp, fw_id]( 283*acb7cfb4SJennifer Lee const boost::system::error_code error_code, 284*acb7cfb4SJennifer Lee const sdbusplus::message::variant<std::string> 285*acb7cfb4SJennifer Lee &activation_status) { 28655c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "safe returned in lambda function"; 2876c4eb9deSJennifer Lee if (error_code) { 288*acb7cfb4SJennifer Lee asyncResp->res.result( 2896c4eb9deSJennifer Lee boost::beast::http::status::internal_server_error); 290*acb7cfb4SJennifer Lee asyncResp->res.jsonValue = messages::internalError(); 291*acb7cfb4SJennifer Lee asyncResp->res.end(); 2926c4eb9deSJennifer Lee return; 2936c4eb9deSJennifer Lee } 294*acb7cfb4SJennifer Lee const std::string *activation_status_str = 295*acb7cfb4SJennifer Lee mapbox::getPtr<const std::string>(activation_status); 296*acb7cfb4SJennifer Lee if (activation_status_str != nullptr && 297*acb7cfb4SJennifer Lee *activation_status_str != 298*acb7cfb4SJennifer Lee "xyz.openbmc_project.Software.Activation." 299*acb7cfb4SJennifer Lee "Activations.Active") { 300*acb7cfb4SJennifer Lee // The activation status of this software is not currently 301*acb7cfb4SJennifer Lee // active, so does not need to be listed in the response 302*acb7cfb4SJennifer Lee return; 303*acb7cfb4SJennifer Lee } 304*acb7cfb4SJennifer Lee asyncResp->res.jsonValue["Members"].push_back( 3056c4eb9deSJennifer Lee {{"@odata.id", 3066c4eb9deSJennifer Lee "/redfish/v1/UpdateService/FirmwareInventory/" + 307*acb7cfb4SJennifer Lee fw_id}}); 308*acb7cfb4SJennifer Lee asyncResp->res.jsonValue["Members@odata.count"] = 309*acb7cfb4SJennifer Lee asyncResp->res.jsonValue["Members"].size(); 3106c4eb9deSJennifer Lee }, 3116c4eb9deSJennifer Lee connectionName, obj.first, "org.freedesktop.DBus.Properties", 312*acb7cfb4SJennifer Lee "Get", "xyz.openbmc_project.Software.Activation", 313*acb7cfb4SJennifer Lee "Activation"); 3146c4eb9deSJennifer Lee } 3156c4eb9deSJennifer Lee } 316729dae72SJennifer Lee }); 317729dae72SJennifer Lee } 318*acb7cfb4SJennifer Lee 31955c7b7a2SEd Tanous OnDemandSoftwareInventoryProvider softwareInventoryProvider; 320729dae72SJennifer Lee }; 321729dae72SJennifer Lee /** 322729dae72SJennifer Lee * Chassis override class for delivering Chassis Schema 323729dae72SJennifer Lee */ 324729dae72SJennifer Lee class SoftwareInventory : public Node { 325729dae72SJennifer Lee public: 326729dae72SJennifer Lee /* 327729dae72SJennifer Lee * Default Constructor 328729dae72SJennifer Lee */ 329729dae72SJennifer Lee template <typename CrowApp> 330729dae72SJennifer Lee SoftwareInventory(CrowApp &app) 3316c4eb9deSJennifer Lee : Node(app, "/redfish/v1/UpdateService/FirmwareInventory/<str>/", 332729dae72SJennifer Lee std::string()) { 333729dae72SJennifer Lee Node::json["@odata.type"] = "#SoftwareInventory.v1_1_0.SoftwareInventory"; 334729dae72SJennifer Lee Node::json["@odata.context"] = 335729dae72SJennifer Lee "/redfish/v1/$metadata#SoftwareInventory.SoftwareInventory"; 336729dae72SJennifer Lee Node::json["Name"] = "Software Inventory"; 3376c4eb9deSJennifer Lee Node::json["Updateable"] = false; 338*acb7cfb4SJennifer Lee Node::json["Status"]["Health"] = "OK"; 339*acb7cfb4SJennifer Lee Node::json["Status"]["HealthRollup"] = "OK"; 340*acb7cfb4SJennifer Lee Node::json["Status"]["State"] = "Enabled"; 341729dae72SJennifer Lee entityPrivileges = { 342729dae72SJennifer Lee {boost::beast::http::verb::get, {{"Login"}}}, 343729dae72SJennifer Lee {boost::beast::http::verb::head, {{"Login"}}}, 344729dae72SJennifer Lee {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 345729dae72SJennifer Lee {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 346729dae72SJennifer Lee {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 347729dae72SJennifer Lee {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 348729dae72SJennifer Lee } 349729dae72SJennifer Lee 350729dae72SJennifer Lee private: 351729dae72SJennifer Lee /** 352729dae72SJennifer Lee * Functions triggers appropriate requests on DBus 353729dae72SJennifer Lee */ 35455c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 355729dae72SJennifer Lee const std::vector<std::string> ¶ms) override { 35655c7b7a2SEd Tanous res.jsonValue = Node::json; 3576c4eb9deSJennifer Lee 358729dae72SJennifer Lee if (params.size() != 1) { 359729dae72SJennifer Lee res.result(boost::beast::http::status::internal_server_error); 360*acb7cfb4SJennifer Lee res.jsonValue = messages::internalError(); 361729dae72SJennifer Lee res.end(); 362729dae72SJennifer Lee return; 363729dae72SJennifer Lee } 364729dae72SJennifer Lee 365*acb7cfb4SJennifer Lee const std::string &fw_id = params[0]; 366*acb7cfb4SJennifer Lee res.jsonValue["Id"] = fw_id; 36755c7b7a2SEd Tanous res.jsonValue["@odata.id"] = 368*acb7cfb4SJennifer Lee "/redfish/v1/UpdateService/FirmwareInventory/" + fw_id; 369*acb7cfb4SJennifer Lee softwareInventoryProvider.getAllSoftwareInventoryObject([ 370*acb7cfb4SJennifer Lee &res, id{std::string(fw_id)} 371*acb7cfb4SJennifer Lee ](const bool &success, 3726c4eb9deSJennifer Lee const std::vector<std::pair< 3736c4eb9deSJennifer Lee std::string, 3746c4eb9deSJennifer Lee std::vector<std::pair<std::string, std::vector<std::string>>>>> 3756c4eb9deSJennifer Lee &subtree) { 37655c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "doGet callback..."; 3776c4eb9deSJennifer Lee if (!success) { 3786c4eb9deSJennifer Lee res.result(boost::beast::http::status::internal_server_error); 379*acb7cfb4SJennifer Lee res.jsonValue = messages::internalError(); 380729dae72SJennifer Lee res.end(); 3816c4eb9deSJennifer Lee return; 3826c4eb9deSJennifer Lee } 3836c4eb9deSJennifer Lee 3846c4eb9deSJennifer Lee if (subtree.empty()) { 385*acb7cfb4SJennifer Lee BMCWEB_LOG_ERROR << "subtree empty!!"; 386*acb7cfb4SJennifer Lee res.result(boost::beast::http::status::not_found); 3876c4eb9deSJennifer Lee res.end(); 3886c4eb9deSJennifer Lee return; 3896c4eb9deSJennifer Lee } 3906c4eb9deSJennifer Lee 391*acb7cfb4SJennifer Lee bool fw_id_found = false; 392*acb7cfb4SJennifer Lee 3936c4eb9deSJennifer Lee for (auto &obj : subtree) { 394*acb7cfb4SJennifer Lee if (boost::ends_with(obj.first, id) != true) { 395*acb7cfb4SJennifer Lee continue; 396*acb7cfb4SJennifer Lee } 397*acb7cfb4SJennifer Lee fw_id_found = true; 398*acb7cfb4SJennifer Lee 3996c4eb9deSJennifer Lee const std::vector<std::pair<std::string, std::vector<std::string>>> 4006c4eb9deSJennifer Lee &connections = obj.second; 4016c4eb9deSJennifer Lee 402*acb7cfb4SJennifer Lee if (connections.size() <= 0) { 403*acb7cfb4SJennifer Lee continue; 404*acb7cfb4SJennifer Lee } 405*acb7cfb4SJennifer Lee const std::pair<std::string, std::vector<std::string>> &conn = 406*acb7cfb4SJennifer Lee connections[0]; 407*acb7cfb4SJennifer Lee const std::string &connectionName = conn.first; 40855c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "connectionName = " << connectionName; 40955c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "obj.first = " << obj.first; 4106c4eb9deSJennifer Lee 41155c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 412*acb7cfb4SJennifer Lee [&res, id]( 4136c4eb9deSJennifer Lee const boost::system::error_code error_code, 4146c4eb9deSJennifer Lee const boost::container::flat_map<std::string, VariantType> 4156c4eb9deSJennifer Lee &propertiesList) { 4166c4eb9deSJennifer Lee if (error_code) { 417*acb7cfb4SJennifer Lee res.result(boost::beast::http::status::internal_server_error); 418*acb7cfb4SJennifer Lee res.jsonValue = messages::internalError(); 4196c4eb9deSJennifer Lee res.end(); 4206c4eb9deSJennifer Lee return; 4216c4eb9deSJennifer Lee } 422*acb7cfb4SJennifer Lee 4236c4eb9deSJennifer Lee boost::container::flat_map<std::string, 4246c4eb9deSJennifer Lee VariantType>::const_iterator it = 4256c4eb9deSJennifer Lee propertiesList.find("Purpose"); 4266c4eb9deSJennifer Lee if (it == propertiesList.end()) { 427*acb7cfb4SJennifer Lee BMCWEB_LOG_ERROR << "Can't find property \"Purpose\"!"; 428*acb7cfb4SJennifer Lee res.result(boost::beast::http::status::internal_server_error); 429*acb7cfb4SJennifer Lee res.jsonValue = messages::internalError(); 430*acb7cfb4SJennifer Lee res.end(); 4316c4eb9deSJennifer Lee return; 4326c4eb9deSJennifer Lee } 433*acb7cfb4SJennifer Lee 434*acb7cfb4SJennifer Lee // SoftwareId 435*acb7cfb4SJennifer Lee const std::string *sw_inv_purpose = 436*acb7cfb4SJennifer Lee mapbox::getPtr<const std::string>(it->second); 437*acb7cfb4SJennifer Lee if (sw_inv_purpose == nullptr) { 438*acb7cfb4SJennifer Lee res.jsonValue = redfish::messages::internalError(); 439*acb7cfb4SJennifer Lee res.jsonValue = messages::internalError(); 440*acb7cfb4SJennifer Lee return; 441*acb7cfb4SJennifer Lee } 44255c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "sw_inv_purpose = " << sw_inv_purpose; 443*acb7cfb4SJennifer Lee std::size_t last_pos = sw_inv_purpose->rfind("."); 444*acb7cfb4SJennifer Lee if (last_pos != std::string::npos) { 445*acb7cfb4SJennifer Lee res.jsonValue["SoftwareId"] = 446*acb7cfb4SJennifer Lee sw_inv_purpose->substr(last_pos + 1); 447*acb7cfb4SJennifer Lee } else { 448*acb7cfb4SJennifer Lee BMCWEB_LOG_ERROR << "Can't parse software purpose!"; 449*acb7cfb4SJennifer Lee } 450*acb7cfb4SJennifer Lee 451*acb7cfb4SJennifer Lee // Version 4526c4eb9deSJennifer Lee it = propertiesList.find("Version"); 453*acb7cfb4SJennifer Lee if (it != propertiesList.end()) { 454*acb7cfb4SJennifer Lee const std::string *version = 455*acb7cfb4SJennifer Lee mapbox::getPtr<const std::string>(it->second); 456*acb7cfb4SJennifer Lee if (version == nullptr) { 457*acb7cfb4SJennifer Lee res.jsonValue = redfish::messages::internalError(); 458*acb7cfb4SJennifer Lee res.jsonValue = messages::internalError(); 4596c4eb9deSJennifer Lee return; 4606c4eb9deSJennifer Lee } 46155c7b7a2SEd Tanous res.jsonValue["Version"] = 46255c7b7a2SEd Tanous *(mapbox::getPtr<const std::string>(it->second)); 463*acb7cfb4SJennifer Lee } else { 464*acb7cfb4SJennifer Lee BMCWEB_LOG_DEBUG << "Can't find version info!"; 4656c4eb9deSJennifer Lee } 4666c4eb9deSJennifer Lee 467*acb7cfb4SJennifer Lee res.end(); 4686c4eb9deSJennifer Lee }, 4696c4eb9deSJennifer Lee connectionName, obj.first, "org.freedesktop.DBus.Properties", 4706c4eb9deSJennifer Lee "GetAll", "xyz.openbmc_project.Software.Version"); 4716c4eb9deSJennifer Lee } 472*acb7cfb4SJennifer Lee if (!fw_id_found) { 473*acb7cfb4SJennifer Lee res.result(boost::beast::http::status::not_found); 474*acb7cfb4SJennifer Lee res.end(); 475*acb7cfb4SJennifer Lee return; 4766c4eb9deSJennifer Lee } 477729dae72SJennifer Lee }); 478729dae72SJennifer Lee } 479729dae72SJennifer Lee 48055c7b7a2SEd Tanous OnDemandSoftwareInventoryProvider softwareInventoryProvider; 481729dae72SJennifer Lee }; 482729dae72SJennifer Lee 483729dae72SJennifer Lee } // namespace redfish 484