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 { 22729dae72SJennifer Lee 23729dae72SJennifer Lee class OnDemandSoftwareInventoryProvider { 24729dae72SJennifer Lee public: 25729dae72SJennifer Lee template <typename CallbackFunc> 266c4eb9deSJennifer Lee void get_all_software_inventory_object(CallbackFunc &&callback) { 27*55c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 28729dae72SJennifer Lee [callback{std::move(callback)}]( 29729dae72SJennifer Lee const boost::system::error_code error_code, 30729dae72SJennifer Lee const std::vector<std::pair< 31729dae72SJennifer Lee std::string, 32729dae72SJennifer Lee std::vector<std::pair<std::string, std::vector<std::string>>>>> 33729dae72SJennifer Lee &subtree) { 34*55c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "get all software inventory object callback..."; 35729dae72SJennifer Lee if (error_code) { 36729dae72SJennifer Lee // Something wrong on DBus, the error_code is not important at this 37729dae72SJennifer Lee // moment, just return success=false, and empty output. Since size 38729dae72SJennifer Lee // of vector may vary depending on information from Entity Manager, 39729dae72SJennifer Lee // and empty output could not be treated same way as error. 406c4eb9deSJennifer Lee callback(false, subtree); 41729dae72SJennifer Lee return; 42729dae72SJennifer Lee } 43729dae72SJennifer Lee 446c4eb9deSJennifer Lee if (subtree.empty()) { 45*55c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "subtree empty"; 466c4eb9deSJennifer Lee callback(false, subtree); 476c4eb9deSJennifer Lee } else { 48*55c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "subtree has something"; 496c4eb9deSJennifer Lee callback(true, subtree); 50729dae72SJennifer Lee } 51729dae72SJennifer Lee }, 52729dae72SJennifer Lee "xyz.openbmc_project.ObjectMapper", 53729dae72SJennifer Lee "/xyz/openbmc_project/object_mapper", 546c4eb9deSJennifer Lee "xyz.openbmc_project.ObjectMapper", "GetSubTree", 556c4eb9deSJennifer Lee "/xyz/openbmc_project/software", int32_t(1), 56729dae72SJennifer Lee std::array<const char *, 1>{"xyz.openbmc_project.Software.Version"}); 57729dae72SJennifer Lee } 58729dae72SJennifer Lee }; 59729dae72SJennifer Lee 60729dae72SJennifer Lee class UpdateService : public Node { 61729dae72SJennifer Lee public: 62729dae72SJennifer Lee UpdateService(CrowApp &app) : Node(app, "/redfish/v1/UpdateService/") { 63729dae72SJennifer Lee Node::json["@odata.type"] = "#UpdateService.v1_2_0.UpdateService"; 64729dae72SJennifer Lee Node::json["@odata.id"] = "/redfish/v1/UpdateService"; 65729dae72SJennifer Lee Node::json["@odata.context"] = 66729dae72SJennifer Lee "/redfish/v1/$metadata#UpdateService.UpdateService"; 67729dae72SJennifer Lee Node::json["Id"] = "UpdateService"; 68729dae72SJennifer Lee Node::json["Description"] = "Service for Software Update"; 69729dae72SJennifer Lee Node::json["Name"] = "Update Service"; 70729dae72SJennifer Lee Node::json["ServiceEnabled"] = true; // UpdateService cannot be disabled 716c4eb9deSJennifer Lee Node::json["FirmwareInventory"] = { 726c4eb9deSJennifer Lee {"@odata.id", "/redfish/v1/UpdateService/FirmwareInventory"}}; 73729dae72SJennifer Lee 74729dae72SJennifer Lee entityPrivileges = { 75729dae72SJennifer Lee {boost::beast::http::verb::get, {{"Login"}}}, 76729dae72SJennifer Lee {boost::beast::http::verb::head, {{"Login"}}}, 77729dae72SJennifer Lee {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 78729dae72SJennifer Lee {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 79729dae72SJennifer Lee {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 80729dae72SJennifer Lee {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 81729dae72SJennifer Lee } 82729dae72SJennifer Lee 83729dae72SJennifer Lee private: 84*55c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 85729dae72SJennifer Lee const std::vector<std::string> ¶ms) override { 86*55c7b7a2SEd Tanous res.jsonValue = Node::json; 87729dae72SJennifer Lee res.end(); 88729dae72SJennifer Lee } 89729dae72SJennifer Lee }; 90729dae72SJennifer Lee 91729dae72SJennifer Lee class SoftwareInventoryCollection : public Node { 92729dae72SJennifer Lee public: 93729dae72SJennifer Lee /* 94729dae72SJennifer Lee * Default Constructor 95729dae72SJennifer Lee */ 96729dae72SJennifer Lee template <typename CrowApp> 97729dae72SJennifer Lee SoftwareInventoryCollection(CrowApp &app) 986c4eb9deSJennifer Lee : Node(app, "/redfish/v1/UpdateService/FirmwareInventory/") { 99729dae72SJennifer Lee Node::json["@odata.type"] = 100729dae72SJennifer Lee "#SoftwareInventoryCollection.SoftwareInventoryCollection"; 1016c4eb9deSJennifer Lee Node::json["@odata.id"] = "/redfish/v1/UpdateService/FirmwareInventory"; 102729dae72SJennifer Lee Node::json["@odata.context"] = 103729dae72SJennifer Lee "/redfish/v1/" 104729dae72SJennifer Lee "$metadata#SoftwareInventoryCollection.SoftwareInventoryCollection"; 105729dae72SJennifer Lee Node::json["Name"] = "Software Inventory Collection"; 106729dae72SJennifer Lee 107729dae72SJennifer Lee entityPrivileges = { 108729dae72SJennifer Lee {boost::beast::http::verb::get, {{"Login"}}}, 109729dae72SJennifer Lee {boost::beast::http::verb::head, {{"Login"}}}, 110729dae72SJennifer Lee {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 111729dae72SJennifer Lee {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 112729dae72SJennifer Lee {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 113729dae72SJennifer Lee {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 114729dae72SJennifer Lee } 115729dae72SJennifer Lee 116729dae72SJennifer Lee private: 117729dae72SJennifer Lee /** 118729dae72SJennifer Lee * Functions triggers appropriate requests on DBus 119729dae72SJennifer Lee */ 120*55c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 121729dae72SJennifer Lee const std::vector<std::string> ¶ms) override { 122*55c7b7a2SEd Tanous res.jsonValue = Node::json; 123*55c7b7a2SEd Tanous softwareInventoryProvider.get_all_software_inventory_object( 1246c4eb9deSJennifer Lee [&](const bool &success, 1256c4eb9deSJennifer Lee const std::vector<std::pair< 1266c4eb9deSJennifer Lee std::string, 1276c4eb9deSJennifer Lee std::vector<std::pair<std::string, std::vector<std::string>>>>> 1286c4eb9deSJennifer Lee &subtree) { 1296c4eb9deSJennifer Lee if (!success) { 130729dae72SJennifer Lee res.result(boost::beast::http::status::internal_server_error); 1316c4eb9deSJennifer Lee res.end(); 1326c4eb9deSJennifer Lee return; 133729dae72SJennifer Lee } 1346c4eb9deSJennifer Lee 1356c4eb9deSJennifer Lee if (subtree.empty()) { 136*55c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "subtree empty!!"; 137729dae72SJennifer Lee res.end(); 1386c4eb9deSJennifer Lee return; 1396c4eb9deSJennifer Lee } 1406c4eb9deSJennifer Lee 141*55c7b7a2SEd Tanous res.jsonValue["Members"] = nlohmann::json::array(); 1426c4eb9deSJennifer Lee 1436c4eb9deSJennifer Lee for (auto &obj : subtree) { 1446c4eb9deSJennifer Lee const std::vector<std::pair<std::string, std::vector<std::string>>> 1456c4eb9deSJennifer Lee &connections = obj.second; 1466c4eb9deSJennifer Lee 1476c4eb9deSJennifer Lee for (auto &conn : connections) { 1486c4eb9deSJennifer Lee const std::string connectionName = conn.first; 149*55c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "connectionName = " << connectionName; 150*55c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "obj.first = " << obj.first; 1516c4eb9deSJennifer Lee 152*55c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 1536c4eb9deSJennifer Lee [&](const boost::system::error_code error_code, 1546c4eb9deSJennifer Lee const boost::container::flat_map<std::string, VariantType> 1556c4eb9deSJennifer Lee &propertiesList) { 156*55c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "safe returned in lambda function"; 1576c4eb9deSJennifer Lee if (error_code) { 1586c4eb9deSJennifer Lee res.result( 1596c4eb9deSJennifer Lee boost::beast::http::status::internal_server_error); 1606c4eb9deSJennifer Lee res.end(); 1616c4eb9deSJennifer Lee return; 1626c4eb9deSJennifer Lee } 1636c4eb9deSJennifer Lee boost::container::flat_map<std::string, 1646c4eb9deSJennifer Lee VariantType>::const_iterator it = 1656c4eb9deSJennifer Lee propertiesList.find("Purpose"); 1666c4eb9deSJennifer Lee const std::string &sw_inv_purpose = 167*55c7b7a2SEd Tanous *(mapbox::getPtr<const std::string>(it->second)); 1686c4eb9deSJennifer Lee std::size_t last_pos = sw_inv_purpose.rfind("."); 1696c4eb9deSJennifer Lee if (last_pos != std::string::npos) { 170*55c7b7a2SEd Tanous res.jsonValue["Members"].push_back( 1716c4eb9deSJennifer Lee {{"@odata.id", 1726c4eb9deSJennifer Lee "/redfish/v1/UpdateService/FirmwareInventory/" + 1736c4eb9deSJennifer Lee sw_inv_purpose.substr(last_pos + 1)}}); 174*55c7b7a2SEd Tanous res.jsonValue["Members@odata.count"] = 175*55c7b7a2SEd Tanous res.jsonValue["Members"].size(); 1766c4eb9deSJennifer Lee res.end(); 1776c4eb9deSJennifer Lee } 1786c4eb9deSJennifer Lee 1796c4eb9deSJennifer Lee }, 1806c4eb9deSJennifer Lee connectionName, obj.first, "org.freedesktop.DBus.Properties", 1816c4eb9deSJennifer Lee "GetAll", "xyz.openbmc_project.Software.Version"); 1826c4eb9deSJennifer Lee } 1836c4eb9deSJennifer Lee } 184729dae72SJennifer Lee }); 185729dae72SJennifer Lee } 186*55c7b7a2SEd Tanous OnDemandSoftwareInventoryProvider softwareInventoryProvider; 187729dae72SJennifer Lee }; 188729dae72SJennifer Lee /** 189729dae72SJennifer Lee * Chassis override class for delivering Chassis Schema 190729dae72SJennifer Lee */ 191729dae72SJennifer Lee class SoftwareInventory : public Node { 192729dae72SJennifer Lee public: 193729dae72SJennifer Lee /* 194729dae72SJennifer Lee * Default Constructor 195729dae72SJennifer Lee */ 196729dae72SJennifer Lee template <typename CrowApp> 197729dae72SJennifer Lee SoftwareInventory(CrowApp &app) 1986c4eb9deSJennifer Lee : Node(app, "/redfish/v1/UpdateService/FirmwareInventory/<str>/", 199729dae72SJennifer Lee std::string()) { 200729dae72SJennifer Lee Node::json["@odata.type"] = "#SoftwareInventory.v1_1_0.SoftwareInventory"; 201729dae72SJennifer Lee Node::json["@odata.context"] = 202729dae72SJennifer Lee "/redfish/v1/$metadata#SoftwareInventory.SoftwareInventory"; 203729dae72SJennifer Lee Node::json["Name"] = "Software Inventory"; 204729dae72SJennifer Lee Node::json["Status"] = "OK"; // TODO 2056c4eb9deSJennifer Lee Node::json["Updateable"] = false; 206729dae72SJennifer Lee 207729dae72SJennifer Lee entityPrivileges = { 208729dae72SJennifer Lee {boost::beast::http::verb::get, {{"Login"}}}, 209729dae72SJennifer Lee {boost::beast::http::verb::head, {{"Login"}}}, 210729dae72SJennifer Lee {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 211729dae72SJennifer Lee {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 212729dae72SJennifer Lee {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 213729dae72SJennifer Lee {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 214729dae72SJennifer Lee } 215729dae72SJennifer Lee 216729dae72SJennifer Lee private: 217729dae72SJennifer Lee /** 218729dae72SJennifer Lee * Functions triggers appropriate requests on DBus 219729dae72SJennifer Lee */ 220*55c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 221729dae72SJennifer Lee const std::vector<std::string> ¶ms) override { 222*55c7b7a2SEd Tanous res.jsonValue = Node::json; 2236c4eb9deSJennifer Lee 224729dae72SJennifer Lee if (params.size() != 1) { 225729dae72SJennifer Lee res.result(boost::beast::http::status::internal_server_error); 226729dae72SJennifer Lee res.end(); 227729dae72SJennifer Lee return; 228729dae72SJennifer Lee } 229729dae72SJennifer Lee 2306c4eb9deSJennifer Lee const std::string &sw_id = params[0]; 231*55c7b7a2SEd Tanous res.jsonValue["@odata.id"] = 2326c4eb9deSJennifer Lee "/redfish/v1/UpdateService/FirmwareInventory/" + sw_id; 233*55c7b7a2SEd Tanous softwareInventoryProvider.get_all_software_inventory_object( 2346c4eb9deSJennifer Lee [&, id{std::string(sw_id)} ]( 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) { 240*55c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "doGet callback..."; 2416c4eb9deSJennifer Lee if (!success) { 2426c4eb9deSJennifer Lee res.result(boost::beast::http::status::internal_server_error); 243729dae72SJennifer Lee res.end(); 2446c4eb9deSJennifer Lee return; 2456c4eb9deSJennifer Lee } 2466c4eb9deSJennifer Lee 2476c4eb9deSJennifer Lee if (subtree.empty()) { 248*55c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "subtree empty!!"; 2496c4eb9deSJennifer Lee res.end(); 2506c4eb9deSJennifer Lee return; 2516c4eb9deSJennifer Lee } 2526c4eb9deSJennifer Lee 2536c4eb9deSJennifer Lee for (auto &obj : subtree) { 2546c4eb9deSJennifer Lee const std::vector<std::pair<std::string, std::vector<std::string>>> 2556c4eb9deSJennifer Lee &connections = obj.second; 2566c4eb9deSJennifer Lee 2576c4eb9deSJennifer Lee for (auto &conn : connections) { 2586c4eb9deSJennifer Lee const std::string connectionName = conn.first; 259*55c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "connectionName = " << connectionName; 260*55c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "obj.first = " << obj.first; 2616c4eb9deSJennifer Lee 262*55c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 2636c4eb9deSJennifer Lee [&, id{std::string(id)} ]( 2646c4eb9deSJennifer Lee const boost::system::error_code error_code, 2656c4eb9deSJennifer Lee const boost::container::flat_map<std::string, VariantType> 2666c4eb9deSJennifer Lee &propertiesList) { 2676c4eb9deSJennifer Lee if (error_code) { 2686c4eb9deSJennifer Lee res.result( 2696c4eb9deSJennifer Lee boost::beast::http::status::internal_server_error); 2706c4eb9deSJennifer Lee res.end(); 2716c4eb9deSJennifer Lee return; 2726c4eb9deSJennifer Lee } 2736c4eb9deSJennifer Lee boost::container::flat_map<std::string, 2746c4eb9deSJennifer Lee VariantType>::const_iterator it = 2756c4eb9deSJennifer Lee propertiesList.find("Purpose"); 2766c4eb9deSJennifer Lee if (it == propertiesList.end()) { 277*55c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "Can't find property \"Purpose\"!"; 2786c4eb9deSJennifer Lee return; 2796c4eb9deSJennifer Lee } 2806c4eb9deSJennifer Lee const std::string &sw_inv_purpose = 281*55c7b7a2SEd Tanous *(mapbox::getPtr<const std::string>(it->second)); 282*55c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "sw_inv_purpose = " << sw_inv_purpose; 2836c4eb9deSJennifer Lee if (boost::ends_with(sw_inv_purpose, "." + id)) { 2846c4eb9deSJennifer Lee it = propertiesList.find("Version"); 2856c4eb9deSJennifer Lee if (it == propertiesList.end()) { 286*55c7b7a2SEd Tanous BMCWEB_LOG_DEBUG << "Can't find property \"Version\"!"; 2876c4eb9deSJennifer Lee return; 2886c4eb9deSJennifer Lee } 289*55c7b7a2SEd Tanous res.jsonValue["Version"] = 290*55c7b7a2SEd Tanous *(mapbox::getPtr<const std::string>(it->second)); 291*55c7b7a2SEd Tanous res.jsonValue["Id"] = id; 2926c4eb9deSJennifer Lee res.end(); 2936c4eb9deSJennifer Lee } 2946c4eb9deSJennifer Lee 2956c4eb9deSJennifer Lee }, 2966c4eb9deSJennifer Lee connectionName, obj.first, "org.freedesktop.DBus.Properties", 2976c4eb9deSJennifer Lee "GetAll", "xyz.openbmc_project.Software.Version"); 2986c4eb9deSJennifer Lee } 2996c4eb9deSJennifer Lee } 300729dae72SJennifer Lee }); 301729dae72SJennifer Lee } 302729dae72SJennifer Lee 303*55c7b7a2SEd Tanous OnDemandSoftwareInventoryProvider softwareInventoryProvider; 304729dae72SJennifer Lee }; 305729dae72SJennifer Lee 306729dae72SJennifer Lee } // namespace redfish 307