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> 26*6c4eb9deSJennifer Lee void get_all_software_inventory_object(CallbackFunc &&callback) { 27729dae72SJennifer Lee crow::connections::system_bus->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*6c4eb9deSJennifer Lee CROW_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. 40*6c4eb9deSJennifer Lee callback(false, subtree); 41729dae72SJennifer Lee return; 42729dae72SJennifer Lee } 43729dae72SJennifer Lee 44*6c4eb9deSJennifer Lee if (subtree.empty()) { 45*6c4eb9deSJennifer Lee CROW_LOG_DEBUG << "subtree empty"; 46*6c4eb9deSJennifer Lee callback(false, subtree); 47*6c4eb9deSJennifer Lee } else { 48*6c4eb9deSJennifer Lee CROW_LOG_DEBUG << "subtree has something"; 49*6c4eb9deSJennifer Lee callback(true, subtree); 50729dae72SJennifer Lee } 51729dae72SJennifer Lee }, 52729dae72SJennifer Lee "xyz.openbmc_project.ObjectMapper", 53729dae72SJennifer Lee "/xyz/openbmc_project/object_mapper", 54*6c4eb9deSJennifer Lee "xyz.openbmc_project.ObjectMapper", "GetSubTree", 55*6c4eb9deSJennifer 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 71*6c4eb9deSJennifer Lee Node::json["FirmwareInventory"] = { 72*6c4eb9deSJennifer 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: 84729dae72SJennifer Lee void doGet(crow::response &res, const crow::request &req, 85729dae72SJennifer Lee const std::vector<std::string> ¶ms) override { 86729dae72SJennifer Lee res.json_value = 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) 98*6c4eb9deSJennifer Lee : Node(app, "/redfish/v1/UpdateService/FirmwareInventory/") { 99729dae72SJennifer Lee Node::json["@odata.type"] = 100729dae72SJennifer Lee "#SoftwareInventoryCollection.SoftwareInventoryCollection"; 101*6c4eb9deSJennifer 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 */ 120729dae72SJennifer Lee void doGet(crow::response &res, const crow::request &req, 121729dae72SJennifer Lee const std::vector<std::string> ¶ms) override { 122729dae72SJennifer Lee res.json_value = Node::json; 123*6c4eb9deSJennifer Lee software_inventory_provider.get_all_software_inventory_object( 124*6c4eb9deSJennifer Lee [&](const bool &success, 125*6c4eb9deSJennifer Lee const std::vector<std::pair< 126*6c4eb9deSJennifer Lee std::string, 127*6c4eb9deSJennifer Lee std::vector<std::pair<std::string, std::vector<std::string>>>>> 128*6c4eb9deSJennifer Lee &subtree) { 129*6c4eb9deSJennifer Lee if (!success) { 130729dae72SJennifer Lee res.result(boost::beast::http::status::internal_server_error); 131*6c4eb9deSJennifer Lee res.end(); 132*6c4eb9deSJennifer Lee return; 133729dae72SJennifer Lee } 134*6c4eb9deSJennifer Lee 135*6c4eb9deSJennifer Lee if (subtree.empty()) { 136*6c4eb9deSJennifer Lee CROW_LOG_DEBUG << "subtree empty!!"; 137729dae72SJennifer Lee res.end(); 138*6c4eb9deSJennifer Lee return; 139*6c4eb9deSJennifer Lee } 140*6c4eb9deSJennifer Lee 141*6c4eb9deSJennifer Lee res.json_value["Members"] = nlohmann::json::array(); 142*6c4eb9deSJennifer Lee 143*6c4eb9deSJennifer Lee for (auto &obj : subtree) { 144*6c4eb9deSJennifer Lee const std::vector<std::pair<std::string, std::vector<std::string>>> 145*6c4eb9deSJennifer Lee &connections = obj.second; 146*6c4eb9deSJennifer Lee 147*6c4eb9deSJennifer Lee for (auto &conn : connections) { 148*6c4eb9deSJennifer Lee const std::string connectionName = conn.first; 149*6c4eb9deSJennifer Lee CROW_LOG_DEBUG << "connectionName = " << connectionName; 150*6c4eb9deSJennifer Lee CROW_LOG_DEBUG << "obj.first = " << obj.first; 151*6c4eb9deSJennifer Lee 152*6c4eb9deSJennifer Lee crow::connections::system_bus->async_method_call( 153*6c4eb9deSJennifer Lee [&](const boost::system::error_code error_code, 154*6c4eb9deSJennifer Lee const boost::container::flat_map<std::string, VariantType> 155*6c4eb9deSJennifer Lee &propertiesList) { 156*6c4eb9deSJennifer Lee CROW_LOG_DEBUG << "safe returned in lambda function"; 157*6c4eb9deSJennifer Lee if (error_code) { 158*6c4eb9deSJennifer Lee res.result( 159*6c4eb9deSJennifer Lee boost::beast::http::status::internal_server_error); 160*6c4eb9deSJennifer Lee res.end(); 161*6c4eb9deSJennifer Lee return; 162*6c4eb9deSJennifer Lee } 163*6c4eb9deSJennifer Lee boost::container::flat_map<std::string, 164*6c4eb9deSJennifer Lee VariantType>::const_iterator it = 165*6c4eb9deSJennifer Lee propertiesList.find("Purpose"); 166*6c4eb9deSJennifer Lee const std::string &sw_inv_purpose = 167*6c4eb9deSJennifer Lee *(mapbox::get_ptr<const std::string>(it->second)); 168*6c4eb9deSJennifer Lee std::size_t last_pos = sw_inv_purpose.rfind("."); 169*6c4eb9deSJennifer Lee if (last_pos != std::string::npos) { 170*6c4eb9deSJennifer Lee res.json_value["Members"].push_back( 171*6c4eb9deSJennifer Lee {{"@odata.id", 172*6c4eb9deSJennifer Lee "/redfish/v1/UpdateService/FirmwareInventory/" + 173*6c4eb9deSJennifer Lee sw_inv_purpose.substr(last_pos + 1)}}); 174*6c4eb9deSJennifer Lee res.json_value["Members@odata.count"] = 175*6c4eb9deSJennifer Lee res.json_value["Members"].size(); 176*6c4eb9deSJennifer Lee res.end(); 177*6c4eb9deSJennifer Lee } 178*6c4eb9deSJennifer Lee 179*6c4eb9deSJennifer Lee }, 180*6c4eb9deSJennifer Lee connectionName, obj.first, "org.freedesktop.DBus.Properties", 181*6c4eb9deSJennifer Lee "GetAll", "xyz.openbmc_project.Software.Version"); 182*6c4eb9deSJennifer Lee } 183*6c4eb9deSJennifer Lee } 184729dae72SJennifer Lee }); 185729dae72SJennifer Lee } 186729dae72SJennifer Lee OnDemandSoftwareInventoryProvider software_inventory_provider; 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) 198*6c4eb9deSJennifer 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 205*6c4eb9deSJennifer 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 */ 220729dae72SJennifer Lee void doGet(crow::response &res, const crow::request &req, 221729dae72SJennifer Lee const std::vector<std::string> ¶ms) override { 222*6c4eb9deSJennifer Lee res.json_value = Node::json; 223*6c4eb9deSJennifer 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 230*6c4eb9deSJennifer Lee const std::string &sw_id = params[0]; 231*6c4eb9deSJennifer Lee res.json_value["@odata.id"] = 232*6c4eb9deSJennifer Lee "/redfish/v1/UpdateService/FirmwareInventory/" + sw_id; 233*6c4eb9deSJennifer Lee software_inventory_provider.get_all_software_inventory_object( 234*6c4eb9deSJennifer Lee [&, id{std::string(sw_id)} ]( 235*6c4eb9deSJennifer Lee const bool &success, 236*6c4eb9deSJennifer Lee const std::vector<std::pair< 237*6c4eb9deSJennifer Lee std::string, 238*6c4eb9deSJennifer Lee std::vector<std::pair<std::string, std::vector<std::string>>>>> 239*6c4eb9deSJennifer Lee &subtree) { 240*6c4eb9deSJennifer Lee CROW_LOG_DEBUG << "doGet callback..."; 241*6c4eb9deSJennifer Lee if (!success) { 242*6c4eb9deSJennifer Lee res.result(boost::beast::http::status::internal_server_error); 243729dae72SJennifer Lee res.end(); 244*6c4eb9deSJennifer Lee return; 245*6c4eb9deSJennifer Lee } 246*6c4eb9deSJennifer Lee 247*6c4eb9deSJennifer Lee if (subtree.empty()) { 248*6c4eb9deSJennifer Lee CROW_LOG_DEBUG << "subtree empty!!"; 249*6c4eb9deSJennifer Lee res.end(); 250*6c4eb9deSJennifer Lee return; 251*6c4eb9deSJennifer Lee } 252*6c4eb9deSJennifer Lee 253*6c4eb9deSJennifer Lee for (auto &obj : subtree) { 254*6c4eb9deSJennifer Lee const std::vector<std::pair<std::string, std::vector<std::string>>> 255*6c4eb9deSJennifer Lee &connections = obj.second; 256*6c4eb9deSJennifer Lee 257*6c4eb9deSJennifer Lee for (auto &conn : connections) { 258*6c4eb9deSJennifer Lee const std::string connectionName = conn.first; 259*6c4eb9deSJennifer Lee CROW_LOG_DEBUG << "connectionName = " << connectionName; 260*6c4eb9deSJennifer Lee CROW_LOG_DEBUG << "obj.first = " << obj.first; 261*6c4eb9deSJennifer Lee 262*6c4eb9deSJennifer Lee crow::connections::system_bus->async_method_call( 263*6c4eb9deSJennifer Lee [&, id{std::string(id)} ]( 264*6c4eb9deSJennifer Lee const boost::system::error_code error_code, 265*6c4eb9deSJennifer Lee const boost::container::flat_map<std::string, VariantType> 266*6c4eb9deSJennifer Lee &propertiesList) { 267*6c4eb9deSJennifer Lee if (error_code) { 268*6c4eb9deSJennifer Lee res.result( 269*6c4eb9deSJennifer Lee boost::beast::http::status::internal_server_error); 270*6c4eb9deSJennifer Lee res.end(); 271*6c4eb9deSJennifer Lee return; 272*6c4eb9deSJennifer Lee } 273*6c4eb9deSJennifer Lee boost::container::flat_map<std::string, 274*6c4eb9deSJennifer Lee VariantType>::const_iterator it = 275*6c4eb9deSJennifer Lee propertiesList.find("Purpose"); 276*6c4eb9deSJennifer Lee if (it == propertiesList.end()) { 277*6c4eb9deSJennifer Lee CROW_LOG_DEBUG << "Can't find property \"Purpose\"!"; 278*6c4eb9deSJennifer Lee return; 279*6c4eb9deSJennifer Lee } 280*6c4eb9deSJennifer Lee const std::string &sw_inv_purpose = 281*6c4eb9deSJennifer Lee *(mapbox::get_ptr<const std::string>(it->second)); 282*6c4eb9deSJennifer Lee CROW_LOG_DEBUG << "sw_inv_purpose = " << sw_inv_purpose; 283*6c4eb9deSJennifer Lee if (boost::ends_with(sw_inv_purpose, "." + id)) { 284*6c4eb9deSJennifer Lee it = propertiesList.find("Version"); 285*6c4eb9deSJennifer Lee if (it == propertiesList.end()) { 286*6c4eb9deSJennifer Lee CROW_LOG_DEBUG << "Can't find property \"Version\"!"; 287*6c4eb9deSJennifer Lee return; 288*6c4eb9deSJennifer Lee } 289*6c4eb9deSJennifer Lee res.json_value["Version"] = 290*6c4eb9deSJennifer Lee *(mapbox::get_ptr<const std::string>(it->second)); 291*6c4eb9deSJennifer Lee res.json_value["Id"] = id; 292*6c4eb9deSJennifer Lee res.end(); 293*6c4eb9deSJennifer Lee } 294*6c4eb9deSJennifer Lee 295*6c4eb9deSJennifer Lee }, 296*6c4eb9deSJennifer Lee connectionName, obj.first, "org.freedesktop.DBus.Properties", 297*6c4eb9deSJennifer Lee "GetAll", "xyz.openbmc_project.Software.Version"); 298*6c4eb9deSJennifer Lee } 299*6c4eb9deSJennifer Lee } 300729dae72SJennifer Lee }); 301729dae72SJennifer Lee } 302729dae72SJennifer Lee 303729dae72SJennifer Lee OnDemandSoftwareInventoryProvider software_inventory_provider; 304729dae72SJennifer Lee }; 305729dae72SJennifer Lee 306729dae72SJennifer Lee } // namespace redfish 307