1107077deSPrzemyslaw Czarnowski /* 2107077deSPrzemyslaw Czarnowski // Copyright (c) 2018 Intel Corporation 3107077deSPrzemyslaw Czarnowski // 4107077deSPrzemyslaw Czarnowski // Licensed under the Apache License, Version 2.0 (the "License"); 5107077deSPrzemyslaw Czarnowski // you may not use this file except in compliance with the License. 6107077deSPrzemyslaw Czarnowski // You may obtain a copy of the License at 7107077deSPrzemyslaw Czarnowski // 8107077deSPrzemyslaw Czarnowski // http://www.apache.org/licenses/LICENSE-2.0 9107077deSPrzemyslaw Czarnowski // 10107077deSPrzemyslaw Czarnowski // Unless required by applicable law or agreed to in writing, software 11107077deSPrzemyslaw Czarnowski // distributed under the License is distributed on an "AS IS" BASIS, 12107077deSPrzemyslaw Czarnowski // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13107077deSPrzemyslaw Czarnowski // See the License for the specific language governing permissions and 14107077deSPrzemyslaw Czarnowski // limitations under the License. 15107077deSPrzemyslaw Czarnowski */ 16107077deSPrzemyslaw Czarnowski #pragma once 17107077deSPrzemyslaw Czarnowski 18107077deSPrzemyslaw Czarnowski #include <boost/container/flat_map.hpp> 19988fb7b2SAdrian Ambrożewicz #include <boost/process/async_pipe.hpp> 20988fb7b2SAdrian Ambrożewicz #include <boost/type_traits/has_dereference.hpp> 21107077deSPrzemyslaw Czarnowski #include <node.hpp> 22107077deSPrzemyslaw Czarnowski #include <utils/json_utils.hpp> 23107077deSPrzemyslaw Czarnowski // for GetObjectType and ManagedObjectType 24e13c2760SPrzemyslaw Czarnowski #include <account_service.hpp> 259e319cf0SAnna Platash #include <boost/url/url_view.hpp> 26107077deSPrzemyslaw Czarnowski 27107077deSPrzemyslaw Czarnowski namespace redfish 28107077deSPrzemyslaw Czarnowski 29107077deSPrzemyslaw Czarnowski { 309e319cf0SAnna Platash /** 319e319cf0SAnna Platash * @brief Function extracts transfer protocol name from URI. 329e319cf0SAnna Platash */ 339e319cf0SAnna Platash static std::string getTransferProtocolTypeFromUri(const std::string& imageUri) 349e319cf0SAnna Platash { 359e319cf0SAnna Platash try 369e319cf0SAnna Platash { 379e319cf0SAnna Platash std::string_view scheme = boost::urls::url_view(imageUri).scheme(); 389e319cf0SAnna Platash if (scheme == "smb") 399e319cf0SAnna Platash { 409e319cf0SAnna Platash return "CIFS"; 419e319cf0SAnna Platash } 429e319cf0SAnna Platash else if (scheme == "https") 439e319cf0SAnna Platash { 449e319cf0SAnna Platash return "HTTPS"; 459e319cf0SAnna Platash } 469e319cf0SAnna Platash } 479e319cf0SAnna Platash catch (std::exception& p) 489e319cf0SAnna Platash { 499e319cf0SAnna Platash BMCWEB_LOG_ERROR << p.what(); 509e319cf0SAnna Platash } 519e319cf0SAnna Platash return "None"; 529e319cf0SAnna Platash } 53107077deSPrzemyslaw Czarnowski 54107077deSPrzemyslaw Czarnowski /** 55107077deSPrzemyslaw Czarnowski * @brief Read all known properties from VM object interfaces 56107077deSPrzemyslaw Czarnowski */ 57107077deSPrzemyslaw Czarnowski static void vmParseInterfaceObject(const DbusInterfaceType& interface, 5881ce609eSEd Tanous const std::shared_ptr<AsyncResp>& aResp) 59107077deSPrzemyslaw Czarnowski { 60107077deSPrzemyslaw Czarnowski const auto mountPointIface = 61107077deSPrzemyslaw Czarnowski interface.find("xyz.openbmc_project.VirtualMedia.MountPoint"); 62107077deSPrzemyslaw Czarnowski if (mountPointIface == interface.cend()) 63107077deSPrzemyslaw Czarnowski { 64107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Interface MountPoint not found"; 65107077deSPrzemyslaw Czarnowski return; 66107077deSPrzemyslaw Czarnowski } 67107077deSPrzemyslaw Czarnowski 68107077deSPrzemyslaw Czarnowski const auto processIface = 69107077deSPrzemyslaw Czarnowski interface.find("xyz.openbmc_project.VirtualMedia.Process"); 70107077deSPrzemyslaw Czarnowski if (processIface == interface.cend()) 71107077deSPrzemyslaw Czarnowski { 72107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Interface Process not found"; 73107077deSPrzemyslaw Czarnowski return; 74107077deSPrzemyslaw Czarnowski } 75107077deSPrzemyslaw Czarnowski 76107077deSPrzemyslaw Czarnowski const auto endpointIdProperty = mountPointIface->second.find("EndpointId"); 77107077deSPrzemyslaw Czarnowski if (endpointIdProperty == mountPointIface->second.cend()) 78107077deSPrzemyslaw Czarnowski { 79107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Property EndpointId not found"; 80107077deSPrzemyslaw Czarnowski return; 81107077deSPrzemyslaw Czarnowski } 82107077deSPrzemyslaw Czarnowski 83107077deSPrzemyslaw Czarnowski const auto activeProperty = processIface->second.find("Active"); 84107077deSPrzemyslaw Czarnowski if (activeProperty == processIface->second.cend()) 85107077deSPrzemyslaw Czarnowski { 86107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Property Active not found"; 87107077deSPrzemyslaw Czarnowski return; 88107077deSPrzemyslaw Czarnowski } 89107077deSPrzemyslaw Czarnowski 90107077deSPrzemyslaw Czarnowski const bool* activeValue = std::get_if<bool>(&activeProperty->second); 91107077deSPrzemyslaw Czarnowski if (!activeValue) 92107077deSPrzemyslaw Czarnowski { 93107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Value Active not found"; 94107077deSPrzemyslaw Czarnowski return; 95107077deSPrzemyslaw Czarnowski } 96107077deSPrzemyslaw Czarnowski 97107077deSPrzemyslaw Czarnowski const std::string* endpointIdValue = 98107077deSPrzemyslaw Czarnowski std::get_if<std::string>(&endpointIdProperty->second); 99107077deSPrzemyslaw Czarnowski if (endpointIdValue) 100107077deSPrzemyslaw Czarnowski { 101107077deSPrzemyslaw Czarnowski if (!endpointIdValue->empty()) 102107077deSPrzemyslaw Czarnowski { 103107077deSPrzemyslaw Czarnowski // Proxy mode 104d04ba325SPrzemyslaw Czarnowski aResp->res.jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] = 105d04ba325SPrzemyslaw Czarnowski *endpointIdValue; 106107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["TransferProtocolType"] = "OEM"; 107107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Inserted"] = *activeValue; 108107077deSPrzemyslaw Czarnowski if (*activeValue == true) 109107077deSPrzemyslaw Czarnowski { 110107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["ConnectedVia"] = "Applet"; 111107077deSPrzemyslaw Czarnowski } 112107077deSPrzemyslaw Czarnowski } 113107077deSPrzemyslaw Czarnowski else 114107077deSPrzemyslaw Czarnowski { 115107077deSPrzemyslaw Czarnowski // Legacy mode 1169e319cf0SAnna Platash for (const auto& property : mountPointIface->second) 1179e319cf0SAnna Platash { 1189e319cf0SAnna Platash if (property.first == "ImageURL") 119107077deSPrzemyslaw Czarnowski { 120107077deSPrzemyslaw Czarnowski const std::string* imageUrlValue = 1219e319cf0SAnna Platash std::get_if<std::string>(&property.second); 122107077deSPrzemyslaw Czarnowski if (imageUrlValue && !imageUrlValue->empty()) 123107077deSPrzemyslaw Czarnowski { 124da4784d8SPrzemyslaw Czarnowski std::filesystem::path filePath = *imageUrlValue; 125da4784d8SPrzemyslaw Czarnowski if (!filePath.has_filename()) 126da4784d8SPrzemyslaw Czarnowski { 1279e319cf0SAnna Platash // this will handle https share, which not 1289e319cf0SAnna Platash // necessarily has to have filename given. 129da4784d8SPrzemyslaw Czarnowski aResp->res.jsonValue["ImageName"] = ""; 130da4784d8SPrzemyslaw Czarnowski } 131da4784d8SPrzemyslaw Czarnowski else 132da4784d8SPrzemyslaw Czarnowski { 1339e319cf0SAnna Platash aResp->res.jsonValue["ImageName"] = 1349e319cf0SAnna Platash filePath.filename(); 135da4784d8SPrzemyslaw Czarnowski } 136da4784d8SPrzemyslaw Czarnowski 137da4784d8SPrzemyslaw Czarnowski aResp->res.jsonValue["Image"] = *imageUrlValue; 138107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Inserted"] = *activeValue; 1399e319cf0SAnna Platash aResp->res.jsonValue["TransferProtocolType"] = 1409e319cf0SAnna Platash getTransferProtocolTypeFromUri(*imageUrlValue); 1419e319cf0SAnna Platash 142107077deSPrzemyslaw Czarnowski if (*activeValue == true) 143107077deSPrzemyslaw Czarnowski { 144107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["ConnectedVia"] = "URI"; 145107077deSPrzemyslaw Czarnowski } 146107077deSPrzemyslaw Czarnowski } 147107077deSPrzemyslaw Czarnowski } 1489e319cf0SAnna Platash else if (property.first == "WriteProtected") 1499e319cf0SAnna Platash { 1509e319cf0SAnna Platash const bool* writeProtectedValue = 1519e319cf0SAnna Platash std::get_if<bool>(&property.second); 1529e319cf0SAnna Platash if (writeProtectedValue) 1539e319cf0SAnna Platash { 1549e319cf0SAnna Platash aResp->res.jsonValue["WriteProtected"] = 1559e319cf0SAnna Platash *writeProtectedValue; 1569e319cf0SAnna Platash } 1579e319cf0SAnna Platash } 1589e319cf0SAnna Platash } 159107077deSPrzemyslaw Czarnowski } 160107077deSPrzemyslaw Czarnowski } 161107077deSPrzemyslaw Czarnowski } 162107077deSPrzemyslaw Czarnowski 163107077deSPrzemyslaw Czarnowski /** 164107077deSPrzemyslaw Czarnowski * @brief Fill template for Virtual Media Item. 165107077deSPrzemyslaw Czarnowski */ 166107077deSPrzemyslaw Czarnowski static nlohmann::json vmItemTemplate(const std::string& name, 167107077deSPrzemyslaw Czarnowski const std::string& resName) 168107077deSPrzemyslaw Czarnowski { 169107077deSPrzemyslaw Czarnowski nlohmann::json item; 170107077deSPrzemyslaw Czarnowski item["@odata.id"] = 171107077deSPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + resName; 172d04ba325SPrzemyslaw Czarnowski item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia"; 173107077deSPrzemyslaw Czarnowski item["Name"] = "Virtual Removable Media"; 174107077deSPrzemyslaw Czarnowski item["Id"] = resName; 175107077deSPrzemyslaw Czarnowski item["WriteProtected"] = true; 176107077deSPrzemyslaw Czarnowski item["MediaTypes"] = {"CD", "USBStick"}; 177107077deSPrzemyslaw Czarnowski item["TransferMethod"] = "Stream"; 178d04ba325SPrzemyslaw Czarnowski item["Oem"]["OpenBMC"]["@odata.type"] = 179d04ba325SPrzemyslaw Czarnowski "#OemVirtualMedia.v1_0_0.VirtualMedia"; 180107077deSPrzemyslaw Czarnowski 181107077deSPrzemyslaw Czarnowski return item; 182107077deSPrzemyslaw Czarnowski } 183107077deSPrzemyslaw Czarnowski 184107077deSPrzemyslaw Czarnowski /** 185107077deSPrzemyslaw Czarnowski * @brief Fills collection data 186107077deSPrzemyslaw Czarnowski */ 187107077deSPrzemyslaw Czarnowski static void getVmResourceList(std::shared_ptr<AsyncResp> aResp, 188107077deSPrzemyslaw Czarnowski const std::string& service, 189107077deSPrzemyslaw Czarnowski const std::string& name) 190107077deSPrzemyslaw Czarnowski { 191107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Get available Virtual Media resources."; 192107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 193107077deSPrzemyslaw Czarnowski [name, aResp{std::move(aResp)}](const boost::system::error_code ec, 194107077deSPrzemyslaw Czarnowski ManagedObjectType& subtree) { 195107077deSPrzemyslaw Czarnowski if (ec) 196107077deSPrzemyslaw Czarnowski { 197107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 198107077deSPrzemyslaw Czarnowski return; 199107077deSPrzemyslaw Czarnowski } 200107077deSPrzemyslaw Czarnowski nlohmann::json& members = aResp->res.jsonValue["Members"]; 201107077deSPrzemyslaw Czarnowski members = nlohmann::json::array(); 202107077deSPrzemyslaw Czarnowski 203107077deSPrzemyslaw Czarnowski for (const auto& object : subtree) 204107077deSPrzemyslaw Czarnowski { 205107077deSPrzemyslaw Czarnowski nlohmann::json item; 2062dfd18efSEd Tanous std::string path = object.first.filename(); 2072dfd18efSEd Tanous if (path.empty()) 208107077deSPrzemyslaw Czarnowski { 209107077deSPrzemyslaw Czarnowski continue; 210107077deSPrzemyslaw Czarnowski } 211107077deSPrzemyslaw Czarnowski 2122dfd18efSEd Tanous item["@odata.id"] = 213*788ca507SAppaRao Puli "/redfish/v1/Managers/" + name + "/VirtualMedia/" + path; 214107077deSPrzemyslaw Czarnowski 215107077deSPrzemyslaw Czarnowski members.emplace_back(std::move(item)); 216107077deSPrzemyslaw Czarnowski } 217107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Members@odata.count"] = members.size(); 218107077deSPrzemyslaw Czarnowski }, 219107077deSPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 220107077deSPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 221107077deSPrzemyslaw Czarnowski } 222107077deSPrzemyslaw Czarnowski 223107077deSPrzemyslaw Czarnowski /** 224107077deSPrzemyslaw Czarnowski * @brief Fills data for specific resource 225107077deSPrzemyslaw Czarnowski */ 22681ce609eSEd Tanous static void getVmData(const std::shared_ptr<AsyncResp>& aResp, 227107077deSPrzemyslaw Czarnowski const std::string& service, const std::string& name, 228107077deSPrzemyslaw Czarnowski const std::string& resName) 229107077deSPrzemyslaw Czarnowski { 230107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Get Virtual Media resource data."; 231107077deSPrzemyslaw Czarnowski 232107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 233107077deSPrzemyslaw Czarnowski [resName, name, aResp](const boost::system::error_code ec, 234107077deSPrzemyslaw Czarnowski ManagedObjectType& subtree) { 235107077deSPrzemyslaw Czarnowski if (ec) 236107077deSPrzemyslaw Czarnowski { 237107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 238e13c2760SPrzemyslaw Czarnowski 239107077deSPrzemyslaw Czarnowski return; 240107077deSPrzemyslaw Czarnowski } 241107077deSPrzemyslaw Czarnowski 242107077deSPrzemyslaw Czarnowski for (auto& item : subtree) 243107077deSPrzemyslaw Czarnowski { 2442dfd18efSEd Tanous std::string thispath = item.first.filename(); 2452dfd18efSEd Tanous if (thispath.empty()) 246107077deSPrzemyslaw Czarnowski { 247107077deSPrzemyslaw Czarnowski continue; 248107077deSPrzemyslaw Czarnowski } 249107077deSPrzemyslaw Czarnowski 2502dfd18efSEd Tanous if (thispath != resName) 251107077deSPrzemyslaw Czarnowski { 252107077deSPrzemyslaw Czarnowski continue; 253107077deSPrzemyslaw Czarnowski } 254107077deSPrzemyslaw Czarnowski 255107077deSPrzemyslaw Czarnowski aResp->res.jsonValue = vmItemTemplate(name, resName); 256107077deSPrzemyslaw Czarnowski 257e13c2760SPrzemyslaw Czarnowski // Check if dbus path is Legacy type 2582dfd18efSEd Tanous if (thispath.find("VirtualMedia/Legacy") != std::string::npos) 259e13c2760SPrzemyslaw Czarnowski { 260e13c2760SPrzemyslaw Czarnowski aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"] 261e13c2760SPrzemyslaw Czarnowski ["target"] = 262e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + 263e13c2760SPrzemyslaw Czarnowski resName + "/Actions/VirtualMedia.InsertMedia"; 264e13c2760SPrzemyslaw Czarnowski } 265e13c2760SPrzemyslaw Czarnowski 266107077deSPrzemyslaw Czarnowski vmParseInterfaceObject(item.second, aResp); 267107077deSPrzemyslaw Czarnowski 268e13c2760SPrzemyslaw Czarnowski aResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"] 269e13c2760SPrzemyslaw Czarnowski ["target"] = 270e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + 271e13c2760SPrzemyslaw Czarnowski resName + "/Actions/VirtualMedia.EjectMedia"; 272e13c2760SPrzemyslaw Czarnowski 273107077deSPrzemyslaw Czarnowski return; 274107077deSPrzemyslaw Czarnowski } 275107077deSPrzemyslaw Czarnowski 276107077deSPrzemyslaw Czarnowski messages::resourceNotFound( 277d04ba325SPrzemyslaw Czarnowski aResp->res, "#VirtualMedia.v1_3_0.VirtualMedia", resName); 278107077deSPrzemyslaw Czarnowski }, 279107077deSPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 280107077deSPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 281107077deSPrzemyslaw Czarnowski } 282107077deSPrzemyslaw Czarnowski 283e13c2760SPrzemyslaw Czarnowski /** 284e13c2760SPrzemyslaw Czarnowski @brief InsertMedia action class 285e13c2760SPrzemyslaw Czarnowski */ 286e13c2760SPrzemyslaw Czarnowski class VirtualMediaActionInsertMedia : public Node 287e13c2760SPrzemyslaw Czarnowski { 288e13c2760SPrzemyslaw Czarnowski public: 28952cc112dSEd Tanous VirtualMediaActionInsertMedia(App& app) : 290e13c2760SPrzemyslaw Czarnowski Node(app, 291e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/" 292e13c2760SPrzemyslaw Czarnowski "VirtualMedia.InsertMedia", 293e13c2760SPrzemyslaw Czarnowski std::string(), std::string()) 294e13c2760SPrzemyslaw Czarnowski { 295e13c2760SPrzemyslaw Czarnowski entityPrivileges = { 296e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 297e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 298e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 299e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 300e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 301e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 302e13c2760SPrzemyslaw Czarnowski } 303e13c2760SPrzemyslaw Czarnowski 304e13c2760SPrzemyslaw Czarnowski private: 305e13c2760SPrzemyslaw Czarnowski /** 306c6f4e017SAgata Olender * @brief Transfer protocols supported for InsertMedia action. 307c6f4e017SAgata Olender * 308c6f4e017SAgata Olender */ 309c6f4e017SAgata Olender enum class TransferProtocol 310c6f4e017SAgata Olender { 311c6f4e017SAgata Olender https, 312c6f4e017SAgata Olender smb, 313c6f4e017SAgata Olender invalid 314c6f4e017SAgata Olender }; 315c6f4e017SAgata Olender 316c6f4e017SAgata Olender /** 317c6f4e017SAgata Olender * @brief Function extracts transfer protocol type from URI. 318c6f4e017SAgata Olender * 319c6f4e017SAgata Olender */ 320c6f4e017SAgata Olender std::optional<TransferProtocol> 321c6f4e017SAgata Olender getTransferProtocolFromUri(const std::string& imageUri) 322c6f4e017SAgata Olender { 3239e319cf0SAnna Platash try 3249e319cf0SAnna Platash { 3259e319cf0SAnna Platash std::string_view scheme = boost::urls::url_view(imageUri).scheme(); 3269e319cf0SAnna Platash if (scheme == "smb") 327c6f4e017SAgata Olender { 328c6f4e017SAgata Olender return TransferProtocol::smb; 329c6f4e017SAgata Olender } 33081ce609eSEd Tanous if (scheme == "https") 331c6f4e017SAgata Olender { 332c6f4e017SAgata Olender return TransferProtocol::https; 333c6f4e017SAgata Olender } 3349e319cf0SAnna Platash else if (!scheme.empty()) 335c6f4e017SAgata Olender { 336c6f4e017SAgata Olender return TransferProtocol::invalid; 337c6f4e017SAgata Olender } 338c6f4e017SAgata Olender } 3399e319cf0SAnna Platash catch (std::exception& p) 3409e319cf0SAnna Platash { 3419e319cf0SAnna Platash BMCWEB_LOG_ERROR << p.what(); 3429e319cf0SAnna Platash } 3439e319cf0SAnna Platash 3449e319cf0SAnna Platash return {}; 345c6f4e017SAgata Olender } 346c6f4e017SAgata Olender 347c6f4e017SAgata Olender /** 348c6f4e017SAgata Olender * @brief Function convert transfer protocol from string param. 349c6f4e017SAgata Olender * 350c6f4e017SAgata Olender */ 351c6f4e017SAgata Olender std::optional<TransferProtocol> getTransferProtocolFromParam( 352c6f4e017SAgata Olender const std::optional<std::string>& transferProtocolType) 353c6f4e017SAgata Olender { 354c6f4e017SAgata Olender if (transferProtocolType == std::nullopt) 355c6f4e017SAgata Olender { 356c6f4e017SAgata Olender return {}; 357c6f4e017SAgata Olender } 358c6f4e017SAgata Olender 359c6f4e017SAgata Olender if (*transferProtocolType == "CIFS") 360c6f4e017SAgata Olender { 361c6f4e017SAgata Olender return TransferProtocol::smb; 362c6f4e017SAgata Olender } 363c6f4e017SAgata Olender 364c6f4e017SAgata Olender if (*transferProtocolType == "HTTPS") 365c6f4e017SAgata Olender { 366c6f4e017SAgata Olender return TransferProtocol::https; 367c6f4e017SAgata Olender } 368c6f4e017SAgata Olender 369c6f4e017SAgata Olender return TransferProtocol::invalid; 370c6f4e017SAgata Olender } 371c6f4e017SAgata Olender 372c6f4e017SAgata Olender /** 373c6f4e017SAgata Olender * @brief Function extends URI with transfer protocol type. 374c6f4e017SAgata Olender * 375c6f4e017SAgata Olender */ 37681ce609eSEd Tanous std::string 377c6f4e017SAgata Olender getUriWithTransferProtocol(const std::string& imageUri, 378c6f4e017SAgata Olender const TransferProtocol& transferProtocol) 379c6f4e017SAgata Olender { 380c6f4e017SAgata Olender if (transferProtocol == TransferProtocol::smb) 381c6f4e017SAgata Olender { 382c6f4e017SAgata Olender return "smb://" + imageUri; 383c6f4e017SAgata Olender } 384c6f4e017SAgata Olender 385c6f4e017SAgata Olender if (transferProtocol == TransferProtocol::https) 386c6f4e017SAgata Olender { 387c6f4e017SAgata Olender return "https://" + imageUri; 388c6f4e017SAgata Olender } 389c6f4e017SAgata Olender 390c6f4e017SAgata Olender return imageUri; 391c6f4e017SAgata Olender } 392c6f4e017SAgata Olender 393c6f4e017SAgata Olender /** 394c6f4e017SAgata Olender * @brief Function validate parameters of insert media request. 395c6f4e017SAgata Olender * 396c6f4e017SAgata Olender */ 397c6f4e017SAgata Olender bool validateParams(crow::Response& res, std::string& imageUrl, 398c6f4e017SAgata Olender const std::optional<bool>& inserted, 399c6f4e017SAgata Olender const std::optional<std::string>& transferMethod, 400c6f4e017SAgata Olender const std::optional<std::string>& transferProtocolType) 401c6f4e017SAgata Olender { 402c6f4e017SAgata Olender BMCWEB_LOG_DEBUG << "Validation started"; 403c6f4e017SAgata Olender // required param imageUrl must not be empty 404c6f4e017SAgata Olender if (imageUrl.empty()) 405c6f4e017SAgata Olender { 406c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter Image is empty."; 407c6f4e017SAgata Olender 408c6f4e017SAgata Olender messages::propertyValueFormatError(res, "<empty>", "Image"); 409c6f4e017SAgata Olender 410c6f4e017SAgata Olender return false; 411c6f4e017SAgata Olender } 412c6f4e017SAgata Olender 413c6f4e017SAgata Olender // optional param inserted must be true 414c6f4e017SAgata Olender if ((inserted != std::nullopt) && (*inserted != true)) 415c6f4e017SAgata Olender { 416c6f4e017SAgata Olender BMCWEB_LOG_ERROR 417c6f4e017SAgata Olender << "Request action optional parameter Inserted must be true."; 418c6f4e017SAgata Olender 419c6f4e017SAgata Olender messages::actionParameterNotSupported(res, "Inserted", 420c6f4e017SAgata Olender "InsertMedia"); 421c6f4e017SAgata Olender 422c6f4e017SAgata Olender return false; 423c6f4e017SAgata Olender } 424c6f4e017SAgata Olender 425c6f4e017SAgata Olender // optional param transferMethod must be stream 426c6f4e017SAgata Olender if ((transferMethod != std::nullopt) && (*transferMethod != "Stream")) 427c6f4e017SAgata Olender { 428c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action optional parameter " 429c6f4e017SAgata Olender "TransferMethod must be Stream."; 430c6f4e017SAgata Olender 431c6f4e017SAgata Olender messages::actionParameterNotSupported(res, "TransferMethod", 432c6f4e017SAgata Olender "InsertMedia"); 433c6f4e017SAgata Olender 434c6f4e017SAgata Olender return false; 435c6f4e017SAgata Olender } 436c6f4e017SAgata Olender 437c6f4e017SAgata Olender std::optional<TransferProtocol> uriTransferProtocolType = 438c6f4e017SAgata Olender getTransferProtocolFromUri(imageUrl); 439c6f4e017SAgata Olender 440c6f4e017SAgata Olender std::optional<TransferProtocol> paramTransferProtocolType = 441c6f4e017SAgata Olender getTransferProtocolFromParam(transferProtocolType); 442c6f4e017SAgata Olender 443c6f4e017SAgata Olender // ImageUrl does not contain valid protocol type 444c6f4e017SAgata Olender if (*uriTransferProtocolType == TransferProtocol::invalid) 445c6f4e017SAgata Olender { 446c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must " 447c6f4e017SAgata Olender "contain specified protocol type from list: " 448c6f4e017SAgata Olender "(smb, https)."; 449c6f4e017SAgata Olender 450c6f4e017SAgata Olender messages::resourceAtUriInUnknownFormat(res, imageUrl); 451c6f4e017SAgata Olender 452c6f4e017SAgata Olender return false; 453c6f4e017SAgata Olender } 454c6f4e017SAgata Olender 455c6f4e017SAgata Olender // transferProtocolType should contain value from list 456c6f4e017SAgata Olender if (*paramTransferProtocolType == TransferProtocol::invalid) 457c6f4e017SAgata Olender { 458c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType " 459c6f4e017SAgata Olender "must be provided with value from list: " 460c6f4e017SAgata Olender "(CIFS, HTTPS)."; 461c6f4e017SAgata Olender 462c6f4e017SAgata Olender messages::propertyValueNotInList(res, *transferProtocolType, 463c6f4e017SAgata Olender "TransferProtocolType"); 464c6f4e017SAgata Olender return false; 465c6f4e017SAgata Olender } 466c6f4e017SAgata Olender 467c6f4e017SAgata Olender // valid transfer protocol not provided either with URI nor param 468c6f4e017SAgata Olender if ((uriTransferProtocolType == std::nullopt) && 469c6f4e017SAgata Olender (paramTransferProtocolType == std::nullopt)) 470c6f4e017SAgata Olender { 471c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must " 472c6f4e017SAgata Olender "contain specified protocol type or param " 473c6f4e017SAgata Olender "TransferProtocolType must be provided."; 474c6f4e017SAgata Olender 475c6f4e017SAgata Olender messages::resourceAtUriInUnknownFormat(res, imageUrl); 476c6f4e017SAgata Olender 477c6f4e017SAgata Olender return false; 478c6f4e017SAgata Olender } 479c6f4e017SAgata Olender 480c6f4e017SAgata Olender // valid transfer protocol provided both with URI and param 481c6f4e017SAgata Olender if ((paramTransferProtocolType != std::nullopt) && 482c6f4e017SAgata Olender (uriTransferProtocolType != std::nullopt)) 483c6f4e017SAgata Olender { 484c6f4e017SAgata Olender // check if protocol is the same for URI and param 485c6f4e017SAgata Olender if (*paramTransferProtocolType != *uriTransferProtocolType) 486c6f4e017SAgata Olender { 487c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter " 488c6f4e017SAgata Olender "TransferProtocolType must contain the " 489c6f4e017SAgata Olender "same protocol type as protocol type " 490c6f4e017SAgata Olender "provided with param imageUrl."; 491c6f4e017SAgata Olender 492c6f4e017SAgata Olender messages::actionParameterValueTypeError( 493c6f4e017SAgata Olender res, *transferProtocolType, "TransferProtocolType", 494c6f4e017SAgata Olender "InsertMedia"); 495c6f4e017SAgata Olender 496c6f4e017SAgata Olender return false; 497c6f4e017SAgata Olender } 498c6f4e017SAgata Olender } 499c6f4e017SAgata Olender 500c6f4e017SAgata Olender // validation passed 501c6f4e017SAgata Olender // add protocol to URI if needed 502c6f4e017SAgata Olender if (uriTransferProtocolType == std::nullopt) 503c6f4e017SAgata Olender { 504c6f4e017SAgata Olender imageUrl = getUriWithTransferProtocol(imageUrl, 505c6f4e017SAgata Olender *paramTransferProtocolType); 506c6f4e017SAgata Olender } 507c6f4e017SAgata Olender 508c6f4e017SAgata Olender return true; 509c6f4e017SAgata Olender } 510c6f4e017SAgata Olender 511c6f4e017SAgata Olender /** 512e13c2760SPrzemyslaw Czarnowski * @brief Function handles POST method request. 513e13c2760SPrzemyslaw Czarnowski * 514e13c2760SPrzemyslaw Czarnowski * Analyzes POST body message before sends Reset request data to dbus. 515e13c2760SPrzemyslaw Czarnowski */ 516e13c2760SPrzemyslaw Czarnowski void doPost(crow::Response& res, const crow::Request& req, 517e13c2760SPrzemyslaw Czarnowski const std::vector<std::string>& params) override 518e13c2760SPrzemyslaw Czarnowski { 519e13c2760SPrzemyslaw Czarnowski auto aResp = std::make_shared<AsyncResp>(res); 520e13c2760SPrzemyslaw Czarnowski 521e13c2760SPrzemyslaw Czarnowski if (params.size() != 2) 522e13c2760SPrzemyslaw Czarnowski { 523e13c2760SPrzemyslaw Czarnowski messages::internalError(res); 524e13c2760SPrzemyslaw Czarnowski return; 525e13c2760SPrzemyslaw Czarnowski } 526e13c2760SPrzemyslaw Czarnowski 527e13c2760SPrzemyslaw Czarnowski // take resource name from URL 528e13c2760SPrzemyslaw Czarnowski const std::string& resName = params[1]; 529e13c2760SPrzemyslaw Czarnowski 530e13c2760SPrzemyslaw Czarnowski if (params[0] != "bmc") 531e13c2760SPrzemyslaw Czarnowski { 532e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound(res, "VirtualMedia.Insert", resName); 533e13c2760SPrzemyslaw Czarnowski 534e13c2760SPrzemyslaw Czarnowski return; 535e13c2760SPrzemyslaw Czarnowski } 536e13c2760SPrzemyslaw Czarnowski 537e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 538e13c2760SPrzemyslaw Czarnowski [this, aResp{std::move(aResp)}, req, 539e13c2760SPrzemyslaw Czarnowski resName](const boost::system::error_code ec, 540e13c2760SPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 541e13c2760SPrzemyslaw Czarnowski if (ec) 542e13c2760SPrzemyslaw Czarnowski { 543e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 544e13c2760SPrzemyslaw Czarnowski << ec; 545e13c2760SPrzemyslaw Czarnowski messages::internalError(aResp->res); 546e13c2760SPrzemyslaw Czarnowski 547e13c2760SPrzemyslaw Czarnowski return; 548e13c2760SPrzemyslaw Czarnowski } 549e13c2760SPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 550e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 551e13c2760SPrzemyslaw Czarnowski 552e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 55381ce609eSEd Tanous [this, service, resName, req, 55481ce609eSEd Tanous aResp{aResp}](const boost::system::error_code ec, 555e13c2760SPrzemyslaw Czarnowski ManagedObjectType& subtree) { 556e13c2760SPrzemyslaw Czarnowski if (ec) 557e13c2760SPrzemyslaw Czarnowski { 558e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 559e13c2760SPrzemyslaw Czarnowski 560e13c2760SPrzemyslaw Czarnowski return; 561e13c2760SPrzemyslaw Czarnowski } 562e13c2760SPrzemyslaw Czarnowski 563e13c2760SPrzemyslaw Czarnowski for (const auto& object : subtree) 564e13c2760SPrzemyslaw Czarnowski { 565e13c2760SPrzemyslaw Czarnowski const std::string& path = 566e13c2760SPrzemyslaw Czarnowski static_cast<const std::string&>(object.first); 567e13c2760SPrzemyslaw Czarnowski 568f23b7296SEd Tanous std::size_t lastIndex = path.rfind('/'); 569e13c2760SPrzemyslaw Czarnowski if (lastIndex == std::string::npos) 570e13c2760SPrzemyslaw Czarnowski { 571e13c2760SPrzemyslaw Czarnowski continue; 572e13c2760SPrzemyslaw Czarnowski } 573e13c2760SPrzemyslaw Czarnowski 574e13c2760SPrzemyslaw Czarnowski lastIndex += 1; 575e13c2760SPrzemyslaw Czarnowski 576e13c2760SPrzemyslaw Czarnowski if (path.substr(lastIndex) == resName) 577e13c2760SPrzemyslaw Czarnowski { 578e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Proxy"); 579e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 580e13c2760SPrzemyslaw Czarnowski { 581e13c2760SPrzemyslaw Czarnowski // Not possible in proxy mode 582e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "InsertMedia not " 583e13c2760SPrzemyslaw Czarnowski "allowed in proxy mode"; 584e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound( 585e13c2760SPrzemyslaw Czarnowski aResp->res, "VirtualMedia.InsertMedia", 586e13c2760SPrzemyslaw Czarnowski resName); 587e13c2760SPrzemyslaw Czarnowski 588e13c2760SPrzemyslaw Czarnowski return; 589e13c2760SPrzemyslaw Czarnowski } 590e13c2760SPrzemyslaw Czarnowski 591e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Legacy"); 592c6f4e017SAgata Olender if (lastIndex == std::string::npos) 593e13c2760SPrzemyslaw Czarnowski { 594c6f4e017SAgata Olender continue; 595c6f4e017SAgata Olender } 596c6f4e017SAgata Olender 597e13c2760SPrzemyslaw Czarnowski // Legacy mode 598e13c2760SPrzemyslaw Czarnowski std::string imageUrl; 599c6f4e017SAgata Olender std::optional<std::string> userName; 600c6f4e017SAgata Olender std::optional<std::string> password; 601c6f4e017SAgata Olender std::optional<std::string> transferMethod; 602c6f4e017SAgata Olender std::optional<std::string> transferProtocolType; 603c6f4e017SAgata Olender std::optional<bool> writeProtected = true; 604c6f4e017SAgata Olender std::optional<bool> inserted; 605e13c2760SPrzemyslaw Czarnowski 6064e0453b1SGunnar Mills // Read obligatory parameters (url of image) 607d6da5bebSAdrian Ambrożewicz if (!json_util::readJson( 608d6da5bebSAdrian Ambrożewicz req, aResp->res, "Image", imageUrl, 609988fb7b2SAdrian Ambrożewicz "WriteProtected", writeProtected, 610988fb7b2SAdrian Ambrożewicz "UserName", userName, "Password", 611c6f4e017SAgata Olender password, "Inserted", inserted, 612c6f4e017SAgata Olender "TransferMethod", transferMethod, 613c6f4e017SAgata Olender "TransferProtocolType", 614c6f4e017SAgata Olender transferProtocolType)) 615e13c2760SPrzemyslaw Czarnowski { 616c6f4e017SAgata Olender BMCWEB_LOG_DEBUG << "Image is not provided"; 617e13c2760SPrzemyslaw Czarnowski return; 618e13c2760SPrzemyslaw Czarnowski } 619e13c2760SPrzemyslaw Czarnowski 620c6f4e017SAgata Olender bool paramsValid = validateParams( 621c6f4e017SAgata Olender aResp->res, imageUrl, inserted, 622c6f4e017SAgata Olender transferMethod, transferProtocolType); 623c6f4e017SAgata Olender 624c6f4e017SAgata Olender if (paramsValid == false) 625e13c2760SPrzemyslaw Czarnowski { 626e13c2760SPrzemyslaw Czarnowski return; 627e13c2760SPrzemyslaw Czarnowski } 628e13c2760SPrzemyslaw Czarnowski 629c6f4e017SAgata Olender // manager is irrelevant for VirtualMedia dbus 630c6f4e017SAgata Olender // calls 63181ce609eSEd Tanous doMountVmLegacy(aResp, service, resName, 632c6f4e017SAgata Olender imageUrl, !(*writeProtected), 63381ce609eSEd Tanous std::move(*userName), 63481ce609eSEd Tanous std::move(*password)); 635e13c2760SPrzemyslaw Czarnowski 636e13c2760SPrzemyslaw Czarnowski return; 637e13c2760SPrzemyslaw Czarnowski } 638e13c2760SPrzemyslaw Czarnowski } 639e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Parent item not found"; 640e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound(aResp->res, "VirtualMedia", 641e13c2760SPrzemyslaw Czarnowski resName); 642e13c2760SPrzemyslaw Czarnowski }, 643e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 644e13c2760SPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 645e13c2760SPrzemyslaw Czarnowski }, 646e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 647e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 648e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 649e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 650e13c2760SPrzemyslaw Czarnowski } 651e13c2760SPrzemyslaw Czarnowski 6521214b7e7SGunnar Mills template <typename T> 6531214b7e7SGunnar Mills static void secureCleanup(T& value) 654988fb7b2SAdrian Ambrożewicz { 655988fb7b2SAdrian Ambrożewicz auto raw = const_cast<typename T::value_type*>(value.data()); 656988fb7b2SAdrian Ambrożewicz explicit_bzero(raw, value.size() * sizeof(*raw)); 657988fb7b2SAdrian Ambrożewicz } 658988fb7b2SAdrian Ambrożewicz 659988fb7b2SAdrian Ambrożewicz class Credentials 660988fb7b2SAdrian Ambrożewicz { 661988fb7b2SAdrian Ambrożewicz public: 662988fb7b2SAdrian Ambrożewicz Credentials(std::string&& user, std::string&& password) : 663988fb7b2SAdrian Ambrożewicz userBuf(std::move(user)), passBuf(std::move(password)) 6641214b7e7SGunnar Mills {} 665988fb7b2SAdrian Ambrożewicz 666988fb7b2SAdrian Ambrożewicz ~Credentials() 667988fb7b2SAdrian Ambrożewicz { 668988fb7b2SAdrian Ambrożewicz secureCleanup(userBuf); 669988fb7b2SAdrian Ambrożewicz secureCleanup(passBuf); 670988fb7b2SAdrian Ambrożewicz } 671988fb7b2SAdrian Ambrożewicz 672988fb7b2SAdrian Ambrożewicz const std::string& user() 673988fb7b2SAdrian Ambrożewicz { 674988fb7b2SAdrian Ambrożewicz return userBuf; 675988fb7b2SAdrian Ambrożewicz } 676988fb7b2SAdrian Ambrożewicz 677988fb7b2SAdrian Ambrożewicz const std::string& password() 678988fb7b2SAdrian Ambrożewicz { 679988fb7b2SAdrian Ambrożewicz return passBuf; 680988fb7b2SAdrian Ambrożewicz } 681988fb7b2SAdrian Ambrożewicz 682988fb7b2SAdrian Ambrożewicz private: 683988fb7b2SAdrian Ambrożewicz Credentials() = delete; 684988fb7b2SAdrian Ambrożewicz Credentials(const Credentials&) = delete; 685988fb7b2SAdrian Ambrożewicz Credentials& operator=(const Credentials&) = delete; 686988fb7b2SAdrian Ambrożewicz 687988fb7b2SAdrian Ambrożewicz std::string userBuf; 688988fb7b2SAdrian Ambrożewicz std::string passBuf; 689988fb7b2SAdrian Ambrożewicz }; 690988fb7b2SAdrian Ambrożewicz 691988fb7b2SAdrian Ambrożewicz class CredentialsProvider 692988fb7b2SAdrian Ambrożewicz { 693988fb7b2SAdrian Ambrożewicz public: 6941214b7e7SGunnar Mills template <typename T> 6951214b7e7SGunnar Mills struct Deleter 696988fb7b2SAdrian Ambrożewicz { 697988fb7b2SAdrian Ambrożewicz void operator()(T* buff) const 698988fb7b2SAdrian Ambrożewicz { 699988fb7b2SAdrian Ambrożewicz if (buff) 700988fb7b2SAdrian Ambrożewicz { 701988fb7b2SAdrian Ambrożewicz secureCleanup(*buff); 702988fb7b2SAdrian Ambrożewicz delete buff; 703988fb7b2SAdrian Ambrożewicz } 704988fb7b2SAdrian Ambrożewicz } 705988fb7b2SAdrian Ambrożewicz }; 706988fb7b2SAdrian Ambrożewicz 707988fb7b2SAdrian Ambrożewicz using Buffer = std::vector<char>; 708988fb7b2SAdrian Ambrożewicz using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>; 709988fb7b2SAdrian Ambrożewicz // Using explicit definition instead of std::function to avoid implicit 710988fb7b2SAdrian Ambrożewicz // conversions eg. stack copy instead of reference 711988fb7b2SAdrian Ambrożewicz using FormatterFunc = void(const std::string& username, 712988fb7b2SAdrian Ambrożewicz const std::string& password, Buffer& dest); 713988fb7b2SAdrian Ambrożewicz 714988fb7b2SAdrian Ambrożewicz CredentialsProvider(std::string&& user, std::string&& password) : 715988fb7b2SAdrian Ambrożewicz credentials(std::move(user), std::move(password)) 7161214b7e7SGunnar Mills {} 717988fb7b2SAdrian Ambrożewicz 718988fb7b2SAdrian Ambrożewicz const std::string& user() 719988fb7b2SAdrian Ambrożewicz { 720988fb7b2SAdrian Ambrożewicz return credentials.user(); 721988fb7b2SAdrian Ambrożewicz } 722988fb7b2SAdrian Ambrożewicz 723988fb7b2SAdrian Ambrożewicz const std::string& password() 724988fb7b2SAdrian Ambrożewicz { 725988fb7b2SAdrian Ambrożewicz return credentials.password(); 726988fb7b2SAdrian Ambrożewicz } 727988fb7b2SAdrian Ambrożewicz 72881ce609eSEd Tanous SecureBuffer pack(FormatterFunc formatter) 729988fb7b2SAdrian Ambrożewicz { 730988fb7b2SAdrian Ambrożewicz SecureBuffer packed{new Buffer{}}; 731988fb7b2SAdrian Ambrożewicz if (formatter) 732988fb7b2SAdrian Ambrożewicz { 733988fb7b2SAdrian Ambrożewicz formatter(credentials.user(), credentials.password(), *packed); 734988fb7b2SAdrian Ambrożewicz } 735988fb7b2SAdrian Ambrożewicz 736988fb7b2SAdrian Ambrożewicz return packed; 737988fb7b2SAdrian Ambrożewicz } 738988fb7b2SAdrian Ambrożewicz 739988fb7b2SAdrian Ambrożewicz private: 740988fb7b2SAdrian Ambrożewicz Credentials credentials; 741988fb7b2SAdrian Ambrożewicz }; 742988fb7b2SAdrian Ambrożewicz 743988fb7b2SAdrian Ambrożewicz // Wrapper for boost::async_pipe ensuring proper pipe cleanup 7441214b7e7SGunnar Mills template <typename Buffer> 7451214b7e7SGunnar Mills class Pipe 746988fb7b2SAdrian Ambrożewicz { 747988fb7b2SAdrian Ambrożewicz public: 748988fb7b2SAdrian Ambrożewicz using unix_fd = sdbusplus::message::unix_fd; 749988fb7b2SAdrian Ambrożewicz 750988fb7b2SAdrian Ambrożewicz Pipe(boost::asio::io_context& io, Buffer&& buffer) : 751988fb7b2SAdrian Ambrożewicz impl(io), buffer{std::move(buffer)} 7521214b7e7SGunnar Mills {} 753988fb7b2SAdrian Ambrożewicz 754988fb7b2SAdrian Ambrożewicz ~Pipe() 755988fb7b2SAdrian Ambrożewicz { 756988fb7b2SAdrian Ambrożewicz // Named pipe needs to be explicitly removed 757988fb7b2SAdrian Ambrożewicz impl.close(); 758988fb7b2SAdrian Ambrożewicz } 759988fb7b2SAdrian Ambrożewicz 760988fb7b2SAdrian Ambrożewicz unix_fd fd() 761988fb7b2SAdrian Ambrożewicz { 762988fb7b2SAdrian Ambrożewicz return unix_fd{impl.native_source()}; 763988fb7b2SAdrian Ambrożewicz } 764988fb7b2SAdrian Ambrożewicz 765988fb7b2SAdrian Ambrożewicz template <typename WriteHandler> 76681ce609eSEd Tanous void asyncWrite(WriteHandler&& handler) 767988fb7b2SAdrian Ambrożewicz { 768988fb7b2SAdrian Ambrożewicz impl.async_write_some(data(), std::forward<WriteHandler>(handler)); 769988fb7b2SAdrian Ambrożewicz } 770988fb7b2SAdrian Ambrożewicz 771988fb7b2SAdrian Ambrożewicz private: 772988fb7b2SAdrian Ambrożewicz // Specialization for pointer types 773988fb7b2SAdrian Ambrożewicz template <typename B = Buffer> 774988fb7b2SAdrian Ambrożewicz typename std::enable_if<boost::has_dereference<B>::value, 775988fb7b2SAdrian Ambrożewicz boost::asio::const_buffer>::type 776988fb7b2SAdrian Ambrożewicz data() 777988fb7b2SAdrian Ambrożewicz { 778988fb7b2SAdrian Ambrożewicz return boost::asio::buffer(*buffer); 779988fb7b2SAdrian Ambrożewicz } 780988fb7b2SAdrian Ambrożewicz 781988fb7b2SAdrian Ambrożewicz template <typename B = Buffer> 782988fb7b2SAdrian Ambrożewicz typename std::enable_if<!boost::has_dereference<B>::value, 783988fb7b2SAdrian Ambrożewicz boost::asio::const_buffer>::type 784988fb7b2SAdrian Ambrożewicz data() 785988fb7b2SAdrian Ambrożewicz { 786988fb7b2SAdrian Ambrożewicz return boost::asio::buffer(buffer); 787988fb7b2SAdrian Ambrożewicz } 788988fb7b2SAdrian Ambrożewicz 789988fb7b2SAdrian Ambrożewicz const std::string name; 790988fb7b2SAdrian Ambrożewicz boost::process::async_pipe impl; 791988fb7b2SAdrian Ambrożewicz Buffer buffer; 792988fb7b2SAdrian Ambrożewicz }; 793988fb7b2SAdrian Ambrożewicz 794e13c2760SPrzemyslaw Czarnowski /** 795e13c2760SPrzemyslaw Czarnowski * @brief Function transceives data with dbus directly. 796e13c2760SPrzemyslaw Czarnowski * 797e13c2760SPrzemyslaw Czarnowski * All BMC state properties will be retrieved before sending reset request. 798e13c2760SPrzemyslaw Czarnowski */ 79981ce609eSEd Tanous void doMountVmLegacy(const std::shared_ptr<AsyncResp>& asyncResp, 800e13c2760SPrzemyslaw Czarnowski const std::string& service, const std::string& name, 801988fb7b2SAdrian Ambrożewicz const std::string& imageUrl, const bool rw, 802988fb7b2SAdrian Ambrożewicz std::string&& userName, std::string&& password) 803e13c2760SPrzemyslaw Czarnowski { 804988fb7b2SAdrian Ambrożewicz using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>; 805988fb7b2SAdrian Ambrożewicz constexpr const size_t secretLimit = 1024; 806988fb7b2SAdrian Ambrożewicz 807988fb7b2SAdrian Ambrożewicz std::shared_ptr<SecurePipe> secretPipe; 808988fb7b2SAdrian Ambrożewicz std::variant<int, SecurePipe::unix_fd> unixFd = -1; 809988fb7b2SAdrian Ambrożewicz 810988fb7b2SAdrian Ambrożewicz if (!userName.empty() || !password.empty()) 811988fb7b2SAdrian Ambrożewicz { 812988fb7b2SAdrian Ambrożewicz // Encapsulate in safe buffer 813988fb7b2SAdrian Ambrożewicz CredentialsProvider credentials(std::move(userName), 814988fb7b2SAdrian Ambrożewicz std::move(password)); 815988fb7b2SAdrian Ambrożewicz 816988fb7b2SAdrian Ambrożewicz // Payload must contain data + NULL delimiters 817988fb7b2SAdrian Ambrożewicz if (credentials.user().size() + credentials.password().size() + 2 > 818988fb7b2SAdrian Ambrożewicz secretLimit) 819988fb7b2SAdrian Ambrożewicz { 820988fb7b2SAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Credentials too long to handle"; 821988fb7b2SAdrian Ambrożewicz messages::unrecognizedRequestBody(asyncResp->res); 822988fb7b2SAdrian Ambrożewicz return; 823988fb7b2SAdrian Ambrożewicz } 824988fb7b2SAdrian Ambrożewicz 825988fb7b2SAdrian Ambrożewicz // Pack secret 826988fb7b2SAdrian Ambrożewicz auto secret = credentials.pack([](const auto& user, 827988fb7b2SAdrian Ambrożewicz const auto& pass, auto& buff) { 828988fb7b2SAdrian Ambrożewicz std::copy(user.begin(), user.end(), std::back_inserter(buff)); 829988fb7b2SAdrian Ambrożewicz buff.push_back('\0'); 830988fb7b2SAdrian Ambrożewicz std::copy(pass.begin(), pass.end(), std::back_inserter(buff)); 831988fb7b2SAdrian Ambrożewicz buff.push_back('\0'); 832988fb7b2SAdrian Ambrożewicz }); 833988fb7b2SAdrian Ambrożewicz 834988fb7b2SAdrian Ambrożewicz // Open pipe 835988fb7b2SAdrian Ambrożewicz secretPipe = std::make_shared<SecurePipe>( 836988fb7b2SAdrian Ambrożewicz crow::connections::systemBus->get_io_context(), 837988fb7b2SAdrian Ambrożewicz std::move(secret)); 838988fb7b2SAdrian Ambrożewicz unixFd = secretPipe->fd(); 839988fb7b2SAdrian Ambrożewicz 840988fb7b2SAdrian Ambrożewicz // Pass secret over pipe 84181ce609eSEd Tanous secretPipe->asyncWrite( 842f5b16f03SVikram Bodireddy [asyncResp](const boost::system::error_code& ec, std::size_t) { 843988fb7b2SAdrian Ambrożewicz if (ec) 844988fb7b2SAdrian Ambrożewicz { 845988fb7b2SAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec; 846988fb7b2SAdrian Ambrożewicz messages::internalError(asyncResp->res); 847988fb7b2SAdrian Ambrożewicz } 848988fb7b2SAdrian Ambrożewicz }); 849988fb7b2SAdrian Ambrożewicz } 850988fb7b2SAdrian Ambrożewicz 851e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 852988fb7b2SAdrian Ambrożewicz [asyncResp, secretPipe](const boost::system::error_code ec, 853988fb7b2SAdrian Ambrożewicz bool success) { 854e13c2760SPrzemyslaw Czarnowski if (ec) 855e13c2760SPrzemyslaw Czarnowski { 856e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 857e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 858d6da5bebSAdrian Ambrożewicz } 859d6da5bebSAdrian Ambrożewicz else if (!success) 860d6da5bebSAdrian Ambrożewicz { 861d6da5bebSAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Service responded with error"; 862d6da5bebSAdrian Ambrożewicz messages::generalError(asyncResp->res); 863e13c2760SPrzemyslaw Czarnowski } 864e13c2760SPrzemyslaw Czarnowski }, 865e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, 866988fb7b2SAdrian Ambrożewicz "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw, 867988fb7b2SAdrian Ambrożewicz unixFd); 868e13c2760SPrzemyslaw Czarnowski } 869e13c2760SPrzemyslaw Czarnowski }; 870e13c2760SPrzemyslaw Czarnowski 871e13c2760SPrzemyslaw Czarnowski /** 872e13c2760SPrzemyslaw Czarnowski @brief EjectMedia action class 873e13c2760SPrzemyslaw Czarnowski */ 874e13c2760SPrzemyslaw Czarnowski class VirtualMediaActionEjectMedia : public Node 875e13c2760SPrzemyslaw Czarnowski { 876e13c2760SPrzemyslaw Czarnowski public: 87752cc112dSEd Tanous VirtualMediaActionEjectMedia(App& app) : 878e13c2760SPrzemyslaw Czarnowski Node(app, 879e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/" 880e13c2760SPrzemyslaw Czarnowski "VirtualMedia.EjectMedia", 881e13c2760SPrzemyslaw Czarnowski std::string(), std::string()) 882e13c2760SPrzemyslaw Czarnowski { 883e13c2760SPrzemyslaw Czarnowski entityPrivileges = { 884e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 885e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 886e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 887e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 888e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 889e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 890e13c2760SPrzemyslaw Czarnowski } 891e13c2760SPrzemyslaw Czarnowski 892e13c2760SPrzemyslaw Czarnowski private: 893e13c2760SPrzemyslaw Czarnowski /** 894e13c2760SPrzemyslaw Czarnowski * @brief Function handles POST method request. 895e13c2760SPrzemyslaw Czarnowski * 896e13c2760SPrzemyslaw Czarnowski * Analyzes POST body message before sends Reset request data to dbus. 897e13c2760SPrzemyslaw Czarnowski */ 898e13c2760SPrzemyslaw Czarnowski void doPost(crow::Response& res, const crow::Request& req, 899e13c2760SPrzemyslaw Czarnowski const std::vector<std::string>& params) override 900e13c2760SPrzemyslaw Czarnowski { 901e13c2760SPrzemyslaw Czarnowski auto aResp = std::make_shared<AsyncResp>(res); 902e13c2760SPrzemyslaw Czarnowski 903e13c2760SPrzemyslaw Czarnowski if (params.size() != 2) 904e13c2760SPrzemyslaw Czarnowski { 905e13c2760SPrzemyslaw Czarnowski messages::internalError(res); 906e13c2760SPrzemyslaw Czarnowski return; 907e13c2760SPrzemyslaw Czarnowski } 908e13c2760SPrzemyslaw Czarnowski 909e13c2760SPrzemyslaw Czarnowski // take resource name from URL 910e13c2760SPrzemyslaw Czarnowski const std::string& resName = params[1]; 911e13c2760SPrzemyslaw Czarnowski 912e13c2760SPrzemyslaw Czarnowski if (params[0] != "bmc") 913e13c2760SPrzemyslaw Czarnowski { 914e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound(res, "VirtualMedia.Eject", resName); 915e13c2760SPrzemyslaw Czarnowski 916e13c2760SPrzemyslaw Czarnowski return; 917e13c2760SPrzemyslaw Czarnowski } 918e13c2760SPrzemyslaw Czarnowski 919e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 920e13c2760SPrzemyslaw Czarnowski [this, aResp{std::move(aResp)}, req, 921e13c2760SPrzemyslaw Czarnowski resName](const boost::system::error_code ec, 922e13c2760SPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 923e13c2760SPrzemyslaw Czarnowski if (ec) 924e13c2760SPrzemyslaw Czarnowski { 925e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 926e13c2760SPrzemyslaw Czarnowski << ec; 927e13c2760SPrzemyslaw Czarnowski messages::internalError(aResp->res); 928e13c2760SPrzemyslaw Czarnowski 929e13c2760SPrzemyslaw Czarnowski return; 930e13c2760SPrzemyslaw Czarnowski } 931e13c2760SPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 932e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 933e13c2760SPrzemyslaw Czarnowski 934e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 93581ce609eSEd Tanous [this, resName, service, req, 93681ce609eSEd Tanous aResp{aResp}](const boost::system::error_code ec, 937e13c2760SPrzemyslaw Czarnowski ManagedObjectType& subtree) { 938e13c2760SPrzemyslaw Czarnowski if (ec) 939e13c2760SPrzemyslaw Czarnowski { 940e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 941e13c2760SPrzemyslaw Czarnowski 942e13c2760SPrzemyslaw Czarnowski return; 943e13c2760SPrzemyslaw Czarnowski } 944e13c2760SPrzemyslaw Czarnowski 945e13c2760SPrzemyslaw Czarnowski for (const auto& object : subtree) 946e13c2760SPrzemyslaw Czarnowski { 947e13c2760SPrzemyslaw Czarnowski const std::string& path = 948e13c2760SPrzemyslaw Czarnowski static_cast<const std::string&>(object.first); 949e13c2760SPrzemyslaw Czarnowski 950f23b7296SEd Tanous std::size_t lastIndex = path.rfind('/'); 951e13c2760SPrzemyslaw Czarnowski if (lastIndex == std::string::npos) 952e13c2760SPrzemyslaw Czarnowski { 953e13c2760SPrzemyslaw Czarnowski continue; 954e13c2760SPrzemyslaw Czarnowski } 955e13c2760SPrzemyslaw Czarnowski 956e13c2760SPrzemyslaw Czarnowski lastIndex += 1; 957e13c2760SPrzemyslaw Czarnowski 958e13c2760SPrzemyslaw Czarnowski if (path.substr(lastIndex) == resName) 959e13c2760SPrzemyslaw Czarnowski { 960e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Proxy"); 961e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 962e13c2760SPrzemyslaw Czarnowski { 963e13c2760SPrzemyslaw Czarnowski // Proxy mode 96481ce609eSEd Tanous doVmAction(aResp, service, resName, false); 965e13c2760SPrzemyslaw Czarnowski } 966e13c2760SPrzemyslaw Czarnowski 967e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Legacy"); 968e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 969e13c2760SPrzemyslaw Czarnowski { 970e13c2760SPrzemyslaw Czarnowski // Legacy mode 97181ce609eSEd Tanous doVmAction(aResp, service, resName, true); 972e13c2760SPrzemyslaw Czarnowski } 973e13c2760SPrzemyslaw Czarnowski 974e13c2760SPrzemyslaw Czarnowski return; 975e13c2760SPrzemyslaw Czarnowski } 976e13c2760SPrzemyslaw Czarnowski } 977e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Parent item not found"; 978e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound(aResp->res, "VirtualMedia", 979e13c2760SPrzemyslaw Czarnowski resName); 980e13c2760SPrzemyslaw Czarnowski }, 981e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 982e13c2760SPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 983e13c2760SPrzemyslaw Czarnowski }, 984e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 985e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 986e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 987e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 988e13c2760SPrzemyslaw Czarnowski } 989e13c2760SPrzemyslaw Czarnowski 990e13c2760SPrzemyslaw Czarnowski /** 991e13c2760SPrzemyslaw Czarnowski * @brief Function transceives data with dbus directly. 992e13c2760SPrzemyslaw Czarnowski * 993e13c2760SPrzemyslaw Czarnowski * All BMC state properties will be retrieved before sending reset request. 994e13c2760SPrzemyslaw Czarnowski */ 99581ce609eSEd Tanous void doVmAction(const std::shared_ptr<AsyncResp>& asyncResp, 996e13c2760SPrzemyslaw Czarnowski const std::string& service, const std::string& name, 997e13c2760SPrzemyslaw Czarnowski bool legacy) 998e13c2760SPrzemyslaw Czarnowski { 999e13c2760SPrzemyslaw Czarnowski 1000e13c2760SPrzemyslaw Czarnowski // Legacy mount requires parameter with image 1001e13c2760SPrzemyslaw Czarnowski if (legacy) 1002e13c2760SPrzemyslaw Czarnowski { 1003e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1004e13c2760SPrzemyslaw Czarnowski [asyncResp](const boost::system::error_code ec) { 1005e13c2760SPrzemyslaw Czarnowski if (ec) 1006e13c2760SPrzemyslaw Czarnowski { 1007e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 1008e13c2760SPrzemyslaw Czarnowski 1009e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1010e13c2760SPrzemyslaw Czarnowski return; 1011e13c2760SPrzemyslaw Czarnowski } 1012e13c2760SPrzemyslaw Czarnowski }, 1013e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, 1014e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount"); 1015e13c2760SPrzemyslaw Czarnowski } 1016e13c2760SPrzemyslaw Czarnowski else // proxy 1017e13c2760SPrzemyslaw Czarnowski { 1018e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1019e13c2760SPrzemyslaw Czarnowski [asyncResp](const boost::system::error_code ec) { 1020e13c2760SPrzemyslaw Czarnowski if (ec) 1021e13c2760SPrzemyslaw Czarnowski { 1022e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 1023e13c2760SPrzemyslaw Czarnowski 1024e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1025e13c2760SPrzemyslaw Czarnowski return; 1026e13c2760SPrzemyslaw Czarnowski } 1027e13c2760SPrzemyslaw Czarnowski }, 1028e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name, 1029e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount"); 1030e13c2760SPrzemyslaw Czarnowski } 1031e13c2760SPrzemyslaw Czarnowski } 1032e13c2760SPrzemyslaw Czarnowski }; 1033e13c2760SPrzemyslaw Czarnowski 1034107077deSPrzemyslaw Czarnowski class VirtualMediaCollection : public Node 1035107077deSPrzemyslaw Czarnowski { 1036107077deSPrzemyslaw Czarnowski public: 1037107077deSPrzemyslaw Czarnowski /* 1038107077deSPrzemyslaw Czarnowski * Default Constructor 1039107077deSPrzemyslaw Czarnowski */ 104052cc112dSEd Tanous VirtualMediaCollection(App& app) : 1041107077deSPrzemyslaw Czarnowski Node(app, "/redfish/v1/Managers/<str>/VirtualMedia/", std::string()) 1042107077deSPrzemyslaw Czarnowski { 1043107077deSPrzemyslaw Czarnowski entityPrivileges = { 1044107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 1045107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 1046107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 1047107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 1048107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 1049107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 1050107077deSPrzemyslaw Czarnowski } 1051107077deSPrzemyslaw Czarnowski 1052107077deSPrzemyslaw Czarnowski private: 1053107077deSPrzemyslaw Czarnowski /** 1054107077deSPrzemyslaw Czarnowski * Functions triggers appropriate requests on DBus 1055107077deSPrzemyslaw Czarnowski */ 1056f5b16f03SVikram Bodireddy void doGet(crow::Response& res, const crow::Request&, 1057107077deSPrzemyslaw Czarnowski const std::vector<std::string>& params) override 1058107077deSPrzemyslaw Czarnowski { 1059107077deSPrzemyslaw Czarnowski auto asyncResp = std::make_shared<AsyncResp>(res); 1060107077deSPrzemyslaw Czarnowski 1061107077deSPrzemyslaw Czarnowski // Check if there is required param, truly entering this shall be 1062107077deSPrzemyslaw Czarnowski // impossible 1063107077deSPrzemyslaw Czarnowski if (params.size() != 1) 1064107077deSPrzemyslaw Czarnowski { 1065107077deSPrzemyslaw Czarnowski messages::internalError(res); 1066107077deSPrzemyslaw Czarnowski 1067107077deSPrzemyslaw Czarnowski return; 1068107077deSPrzemyslaw Czarnowski } 1069107077deSPrzemyslaw Czarnowski 1070107077deSPrzemyslaw Czarnowski const std::string& name = params[0]; 1071107077deSPrzemyslaw Czarnowski 1072107077deSPrzemyslaw Czarnowski if (name != "bmc") 1073107077deSPrzemyslaw Czarnowski { 1074107077deSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, "VirtualMedia", name); 1075107077deSPrzemyslaw Czarnowski 1076107077deSPrzemyslaw Czarnowski return; 1077107077deSPrzemyslaw Czarnowski } 1078107077deSPrzemyslaw Czarnowski 1079107077deSPrzemyslaw Czarnowski res.jsonValue["@odata.type"] = 1080107077deSPrzemyslaw Czarnowski "#VirtualMediaCollection.VirtualMediaCollection"; 1081107077deSPrzemyslaw Czarnowski res.jsonValue["Name"] = "Virtual Media Services"; 1082107077deSPrzemyslaw Czarnowski res.jsonValue["@odata.id"] = 1083d6c414f3SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia"; 1084107077deSPrzemyslaw Czarnowski 1085107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1086107077deSPrzemyslaw Czarnowski [asyncResp, name](const boost::system::error_code ec, 1087107077deSPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 1088107077deSPrzemyslaw Czarnowski if (ec) 1089107077deSPrzemyslaw Czarnowski { 1090107077deSPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 1091107077deSPrzemyslaw Czarnowski << ec; 1092107077deSPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1093107077deSPrzemyslaw Czarnowski 1094107077deSPrzemyslaw Czarnowski return; 1095107077deSPrzemyslaw Czarnowski } 1096107077deSPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 1097107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 1098107077deSPrzemyslaw Czarnowski 1099107077deSPrzemyslaw Czarnowski getVmResourceList(asyncResp, service, name); 1100107077deSPrzemyslaw Czarnowski }, 1101107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 1102107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 1103107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 1104107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 1105107077deSPrzemyslaw Czarnowski } 1106107077deSPrzemyslaw Czarnowski }; 1107107077deSPrzemyslaw Czarnowski 1108107077deSPrzemyslaw Czarnowski class VirtualMedia : public Node 1109107077deSPrzemyslaw Czarnowski { 1110107077deSPrzemyslaw Czarnowski public: 1111107077deSPrzemyslaw Czarnowski /* 1112107077deSPrzemyslaw Czarnowski * Default Constructor 1113107077deSPrzemyslaw Czarnowski */ 111452cc112dSEd Tanous VirtualMedia(App& app) : 1115107077deSPrzemyslaw Czarnowski Node(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/", 1116107077deSPrzemyslaw Czarnowski std::string(), std::string()) 1117107077deSPrzemyslaw Czarnowski { 1118107077deSPrzemyslaw Czarnowski entityPrivileges = { 1119107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 1120107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 1121107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 1122107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 1123107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 1124107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 1125107077deSPrzemyslaw Czarnowski } 1126107077deSPrzemyslaw Czarnowski 1127107077deSPrzemyslaw Czarnowski private: 1128107077deSPrzemyslaw Czarnowski /** 1129107077deSPrzemyslaw Czarnowski * Functions triggers appropriate requests on DBus 1130107077deSPrzemyslaw Czarnowski */ 1131f5b16f03SVikram Bodireddy void doGet(crow::Response& res, const crow::Request&, 1132107077deSPrzemyslaw Czarnowski const std::vector<std::string>& params) override 1133107077deSPrzemyslaw Czarnowski { 1134107077deSPrzemyslaw Czarnowski // Check if there is required param, truly entering this shall be 1135107077deSPrzemyslaw Czarnowski // impossible 1136107077deSPrzemyslaw Czarnowski if (params.size() != 2) 1137107077deSPrzemyslaw Czarnowski { 1138107077deSPrzemyslaw Czarnowski messages::internalError(res); 1139107077deSPrzemyslaw Czarnowski 1140107077deSPrzemyslaw Czarnowski res.end(); 1141107077deSPrzemyslaw Czarnowski return; 1142107077deSPrzemyslaw Czarnowski } 1143107077deSPrzemyslaw Czarnowski const std::string& name = params[0]; 1144107077deSPrzemyslaw Czarnowski const std::string& resName = params[1]; 1145107077deSPrzemyslaw Czarnowski 1146107077deSPrzemyslaw Czarnowski auto asyncResp = std::make_shared<AsyncResp>(res); 1147107077deSPrzemyslaw Czarnowski 1148107077deSPrzemyslaw Czarnowski if (name != "bmc") 1149107077deSPrzemyslaw Czarnowski { 1150107077deSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName); 1151107077deSPrzemyslaw Czarnowski 1152107077deSPrzemyslaw Czarnowski return; 1153107077deSPrzemyslaw Czarnowski } 1154107077deSPrzemyslaw Czarnowski 1155107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1156107077deSPrzemyslaw Czarnowski [asyncResp, name, resName](const boost::system::error_code ec, 1157107077deSPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 1158107077deSPrzemyslaw Czarnowski if (ec) 1159107077deSPrzemyslaw Czarnowski { 1160107077deSPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 1161107077deSPrzemyslaw Czarnowski << ec; 1162107077deSPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1163107077deSPrzemyslaw Czarnowski 1164107077deSPrzemyslaw Czarnowski return; 1165107077deSPrzemyslaw Czarnowski } 1166107077deSPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 1167107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 1168107077deSPrzemyslaw Czarnowski 1169107077deSPrzemyslaw Czarnowski getVmData(asyncResp, service, name, resName); 1170107077deSPrzemyslaw Czarnowski }, 1171107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 1172107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 1173107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 1174107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 1175107077deSPrzemyslaw Czarnowski } 1176107077deSPrzemyslaw Czarnowski }; 1177107077deSPrzemyslaw Czarnowski 1178107077deSPrzemyslaw Czarnowski } // namespace redfish 1179