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 */ 57*8d1b46d7Szhanghch05 static void 58*8d1b46d7Szhanghch05 vmParseInterfaceObject(const DbusInterfaceType& interface, 59*8d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& aResp) 60107077deSPrzemyslaw Czarnowski { 61107077deSPrzemyslaw Czarnowski const auto mountPointIface = 62107077deSPrzemyslaw Czarnowski interface.find("xyz.openbmc_project.VirtualMedia.MountPoint"); 63107077deSPrzemyslaw Czarnowski if (mountPointIface == interface.cend()) 64107077deSPrzemyslaw Czarnowski { 65107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Interface MountPoint not found"; 66107077deSPrzemyslaw Czarnowski return; 67107077deSPrzemyslaw Czarnowski } 68107077deSPrzemyslaw Czarnowski 69107077deSPrzemyslaw Czarnowski const auto processIface = 70107077deSPrzemyslaw Czarnowski interface.find("xyz.openbmc_project.VirtualMedia.Process"); 71107077deSPrzemyslaw Czarnowski if (processIface == interface.cend()) 72107077deSPrzemyslaw Czarnowski { 73107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Interface Process not found"; 74107077deSPrzemyslaw Czarnowski return; 75107077deSPrzemyslaw Czarnowski } 76107077deSPrzemyslaw Czarnowski 77107077deSPrzemyslaw Czarnowski const auto endpointIdProperty = mountPointIface->second.find("EndpointId"); 78107077deSPrzemyslaw Czarnowski if (endpointIdProperty == mountPointIface->second.cend()) 79107077deSPrzemyslaw Czarnowski { 80107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Property EndpointId not found"; 81107077deSPrzemyslaw Czarnowski return; 82107077deSPrzemyslaw Czarnowski } 83107077deSPrzemyslaw Czarnowski 84107077deSPrzemyslaw Czarnowski const auto activeProperty = processIface->second.find("Active"); 85107077deSPrzemyslaw Czarnowski if (activeProperty == processIface->second.cend()) 86107077deSPrzemyslaw Czarnowski { 87107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Property Active not found"; 88107077deSPrzemyslaw Czarnowski return; 89107077deSPrzemyslaw Czarnowski } 90107077deSPrzemyslaw Czarnowski 91107077deSPrzemyslaw Czarnowski const bool* activeValue = std::get_if<bool>(&activeProperty->second); 92107077deSPrzemyslaw Czarnowski if (!activeValue) 93107077deSPrzemyslaw Czarnowski { 94107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Value Active not found"; 95107077deSPrzemyslaw Czarnowski return; 96107077deSPrzemyslaw Czarnowski } 97107077deSPrzemyslaw Czarnowski 98107077deSPrzemyslaw Czarnowski const std::string* endpointIdValue = 99107077deSPrzemyslaw Czarnowski std::get_if<std::string>(&endpointIdProperty->second); 100107077deSPrzemyslaw Czarnowski if (endpointIdValue) 101107077deSPrzemyslaw Czarnowski { 102107077deSPrzemyslaw Czarnowski if (!endpointIdValue->empty()) 103107077deSPrzemyslaw Czarnowski { 104107077deSPrzemyslaw Czarnowski // Proxy mode 105d04ba325SPrzemyslaw Czarnowski aResp->res.jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] = 106d04ba325SPrzemyslaw Czarnowski *endpointIdValue; 107107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["TransferProtocolType"] = "OEM"; 108107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Inserted"] = *activeValue; 109107077deSPrzemyslaw Czarnowski if (*activeValue == true) 110107077deSPrzemyslaw Czarnowski { 111107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["ConnectedVia"] = "Applet"; 112107077deSPrzemyslaw Czarnowski } 113107077deSPrzemyslaw Czarnowski } 114107077deSPrzemyslaw Czarnowski else 115107077deSPrzemyslaw Czarnowski { 116107077deSPrzemyslaw Czarnowski // Legacy mode 1179e319cf0SAnna Platash for (const auto& property : mountPointIface->second) 1189e319cf0SAnna Platash { 1199e319cf0SAnna Platash if (property.first == "ImageURL") 120107077deSPrzemyslaw Czarnowski { 121107077deSPrzemyslaw Czarnowski const std::string* imageUrlValue = 1229e319cf0SAnna Platash std::get_if<std::string>(&property.second); 123107077deSPrzemyslaw Czarnowski if (imageUrlValue && !imageUrlValue->empty()) 124107077deSPrzemyslaw Czarnowski { 125da4784d8SPrzemyslaw Czarnowski std::filesystem::path filePath = *imageUrlValue; 126da4784d8SPrzemyslaw Czarnowski if (!filePath.has_filename()) 127da4784d8SPrzemyslaw Czarnowski { 1289e319cf0SAnna Platash // this will handle https share, which not 1299e319cf0SAnna Platash // necessarily has to have filename given. 130da4784d8SPrzemyslaw Czarnowski aResp->res.jsonValue["ImageName"] = ""; 131da4784d8SPrzemyslaw Czarnowski } 132da4784d8SPrzemyslaw Czarnowski else 133da4784d8SPrzemyslaw Czarnowski { 1349e319cf0SAnna Platash aResp->res.jsonValue["ImageName"] = 1359e319cf0SAnna Platash filePath.filename(); 136da4784d8SPrzemyslaw Czarnowski } 137da4784d8SPrzemyslaw Czarnowski 138da4784d8SPrzemyslaw Czarnowski aResp->res.jsonValue["Image"] = *imageUrlValue; 139107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Inserted"] = *activeValue; 1409e319cf0SAnna Platash aResp->res.jsonValue["TransferProtocolType"] = 1419e319cf0SAnna Platash getTransferProtocolTypeFromUri(*imageUrlValue); 1429e319cf0SAnna Platash 143107077deSPrzemyslaw Czarnowski if (*activeValue == true) 144107077deSPrzemyslaw Czarnowski { 145107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["ConnectedVia"] = "URI"; 146107077deSPrzemyslaw Czarnowski } 147107077deSPrzemyslaw Czarnowski } 148107077deSPrzemyslaw Czarnowski } 1499e319cf0SAnna Platash else if (property.first == "WriteProtected") 1509e319cf0SAnna Platash { 1519e319cf0SAnna Platash const bool* writeProtectedValue = 1529e319cf0SAnna Platash std::get_if<bool>(&property.second); 1539e319cf0SAnna Platash if (writeProtectedValue) 1549e319cf0SAnna Platash { 1559e319cf0SAnna Platash aResp->res.jsonValue["WriteProtected"] = 1569e319cf0SAnna Platash *writeProtectedValue; 1579e319cf0SAnna Platash } 1589e319cf0SAnna Platash } 1599e319cf0SAnna Platash } 160107077deSPrzemyslaw Czarnowski } 161107077deSPrzemyslaw Czarnowski } 162107077deSPrzemyslaw Czarnowski } 163107077deSPrzemyslaw Czarnowski 164107077deSPrzemyslaw Czarnowski /** 165107077deSPrzemyslaw Czarnowski * @brief Fill template for Virtual Media Item. 166107077deSPrzemyslaw Czarnowski */ 167107077deSPrzemyslaw Czarnowski static nlohmann::json vmItemTemplate(const std::string& name, 168107077deSPrzemyslaw Czarnowski const std::string& resName) 169107077deSPrzemyslaw Czarnowski { 170107077deSPrzemyslaw Czarnowski nlohmann::json item; 171107077deSPrzemyslaw Czarnowski item["@odata.id"] = 172107077deSPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + resName; 173d04ba325SPrzemyslaw Czarnowski item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia"; 174107077deSPrzemyslaw Czarnowski item["Name"] = "Virtual Removable Media"; 175107077deSPrzemyslaw Czarnowski item["Id"] = resName; 176107077deSPrzemyslaw Czarnowski item["WriteProtected"] = true; 177107077deSPrzemyslaw Czarnowski item["MediaTypes"] = {"CD", "USBStick"}; 178107077deSPrzemyslaw Czarnowski item["TransferMethod"] = "Stream"; 179d04ba325SPrzemyslaw Czarnowski item["Oem"]["OpenBMC"]["@odata.type"] = 180d04ba325SPrzemyslaw Czarnowski "#OemVirtualMedia.v1_0_0.VirtualMedia"; 181107077deSPrzemyslaw Czarnowski 182107077deSPrzemyslaw Czarnowski return item; 183107077deSPrzemyslaw Czarnowski } 184107077deSPrzemyslaw Czarnowski 185107077deSPrzemyslaw Czarnowski /** 186107077deSPrzemyslaw Czarnowski * @brief Fills collection data 187107077deSPrzemyslaw Czarnowski */ 188*8d1b46d7Szhanghch05 static void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp, 189107077deSPrzemyslaw Czarnowski const std::string& service, 190107077deSPrzemyslaw Czarnowski const std::string& name) 191107077deSPrzemyslaw Czarnowski { 192107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Get available Virtual Media resources."; 193107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 194107077deSPrzemyslaw Czarnowski [name, aResp{std::move(aResp)}](const boost::system::error_code ec, 195107077deSPrzemyslaw Czarnowski ManagedObjectType& subtree) { 196107077deSPrzemyslaw Czarnowski if (ec) 197107077deSPrzemyslaw Czarnowski { 198107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 199107077deSPrzemyslaw Czarnowski return; 200107077deSPrzemyslaw Czarnowski } 201107077deSPrzemyslaw Czarnowski nlohmann::json& members = aResp->res.jsonValue["Members"]; 202107077deSPrzemyslaw Czarnowski members = nlohmann::json::array(); 203107077deSPrzemyslaw Czarnowski 204107077deSPrzemyslaw Czarnowski for (const auto& object : subtree) 205107077deSPrzemyslaw Czarnowski { 206107077deSPrzemyslaw Czarnowski nlohmann::json item; 2072dfd18efSEd Tanous std::string path = object.first.filename(); 2082dfd18efSEd Tanous if (path.empty()) 209107077deSPrzemyslaw Czarnowski { 210107077deSPrzemyslaw Czarnowski continue; 211107077deSPrzemyslaw Czarnowski } 212107077deSPrzemyslaw Czarnowski 2132dfd18efSEd Tanous item["@odata.id"] = 214788ca507SAppaRao Puli "/redfish/v1/Managers/" + name + "/VirtualMedia/" + path; 215107077deSPrzemyslaw Czarnowski 216107077deSPrzemyslaw Czarnowski members.emplace_back(std::move(item)); 217107077deSPrzemyslaw Czarnowski } 218107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Members@odata.count"] = members.size(); 219107077deSPrzemyslaw Czarnowski }, 220107077deSPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 221107077deSPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 222107077deSPrzemyslaw Czarnowski } 223107077deSPrzemyslaw Czarnowski 224107077deSPrzemyslaw Czarnowski /** 225107077deSPrzemyslaw Czarnowski * @brief Fills data for specific resource 226107077deSPrzemyslaw Czarnowski */ 227*8d1b46d7Szhanghch05 static void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 228107077deSPrzemyslaw Czarnowski const std::string& service, const std::string& name, 229107077deSPrzemyslaw Czarnowski const std::string& resName) 230107077deSPrzemyslaw Czarnowski { 231107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Get Virtual Media resource data."; 232107077deSPrzemyslaw Czarnowski 233107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 234107077deSPrzemyslaw Czarnowski [resName, name, aResp](const boost::system::error_code ec, 235107077deSPrzemyslaw Czarnowski ManagedObjectType& subtree) { 236107077deSPrzemyslaw Czarnowski if (ec) 237107077deSPrzemyslaw Czarnowski { 238107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 239e13c2760SPrzemyslaw Czarnowski 240107077deSPrzemyslaw Czarnowski return; 241107077deSPrzemyslaw Czarnowski } 242107077deSPrzemyslaw Czarnowski 243107077deSPrzemyslaw Czarnowski for (auto& item : subtree) 244107077deSPrzemyslaw Czarnowski { 2452dfd18efSEd Tanous std::string thispath = item.first.filename(); 2462dfd18efSEd Tanous if (thispath.empty()) 247107077deSPrzemyslaw Czarnowski { 248107077deSPrzemyslaw Czarnowski continue; 249107077deSPrzemyslaw Czarnowski } 250107077deSPrzemyslaw Czarnowski 2512dfd18efSEd Tanous if (thispath != resName) 252107077deSPrzemyslaw Czarnowski { 253107077deSPrzemyslaw Czarnowski continue; 254107077deSPrzemyslaw Czarnowski } 255107077deSPrzemyslaw Czarnowski 256107077deSPrzemyslaw Czarnowski aResp->res.jsonValue = vmItemTemplate(name, resName); 257107077deSPrzemyslaw Czarnowski 258e13c2760SPrzemyslaw Czarnowski // Check if dbus path is Legacy type 2592dfd18efSEd Tanous if (thispath.find("VirtualMedia/Legacy") != std::string::npos) 260e13c2760SPrzemyslaw Czarnowski { 261e13c2760SPrzemyslaw Czarnowski aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"] 262e13c2760SPrzemyslaw Czarnowski ["target"] = 263e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + 264e13c2760SPrzemyslaw Czarnowski resName + "/Actions/VirtualMedia.InsertMedia"; 265e13c2760SPrzemyslaw Czarnowski } 266e13c2760SPrzemyslaw Czarnowski 267107077deSPrzemyslaw Czarnowski vmParseInterfaceObject(item.second, aResp); 268107077deSPrzemyslaw Czarnowski 269e13c2760SPrzemyslaw Czarnowski aResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"] 270e13c2760SPrzemyslaw Czarnowski ["target"] = 271e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + 272e13c2760SPrzemyslaw Czarnowski resName + "/Actions/VirtualMedia.EjectMedia"; 273e13c2760SPrzemyslaw Czarnowski 274107077deSPrzemyslaw Czarnowski return; 275107077deSPrzemyslaw Czarnowski } 276107077deSPrzemyslaw Czarnowski 277107077deSPrzemyslaw Czarnowski messages::resourceNotFound( 278d04ba325SPrzemyslaw Czarnowski aResp->res, "#VirtualMedia.v1_3_0.VirtualMedia", resName); 279107077deSPrzemyslaw Czarnowski }, 280107077deSPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 281107077deSPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 282107077deSPrzemyslaw Czarnowski } 283107077deSPrzemyslaw Czarnowski 284e13c2760SPrzemyslaw Czarnowski /** 285e13c2760SPrzemyslaw Czarnowski @brief InsertMedia action class 286e13c2760SPrzemyslaw Czarnowski */ 287e13c2760SPrzemyslaw Czarnowski class VirtualMediaActionInsertMedia : public Node 288e13c2760SPrzemyslaw Czarnowski { 289e13c2760SPrzemyslaw Czarnowski public: 29052cc112dSEd Tanous VirtualMediaActionInsertMedia(App& app) : 291e13c2760SPrzemyslaw Czarnowski Node(app, 292e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/" 293e13c2760SPrzemyslaw Czarnowski "VirtualMedia.InsertMedia", 294e13c2760SPrzemyslaw Czarnowski std::string(), std::string()) 295e13c2760SPrzemyslaw Czarnowski { 296e13c2760SPrzemyslaw Czarnowski entityPrivileges = { 297e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 298e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 299e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 300e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 301e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 302e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 303e13c2760SPrzemyslaw Czarnowski } 304e13c2760SPrzemyslaw Czarnowski 305e13c2760SPrzemyslaw Czarnowski private: 306e13c2760SPrzemyslaw Czarnowski /** 307c6f4e017SAgata Olender * @brief Transfer protocols supported for InsertMedia action. 308c6f4e017SAgata Olender * 309c6f4e017SAgata Olender */ 310c6f4e017SAgata Olender enum class TransferProtocol 311c6f4e017SAgata Olender { 312c6f4e017SAgata Olender https, 313c6f4e017SAgata Olender smb, 314c6f4e017SAgata Olender invalid 315c6f4e017SAgata Olender }; 316c6f4e017SAgata Olender 317c6f4e017SAgata Olender /** 318c6f4e017SAgata Olender * @brief Function extracts transfer protocol type from URI. 319c6f4e017SAgata Olender * 320c6f4e017SAgata Olender */ 321c6f4e017SAgata Olender std::optional<TransferProtocol> 322c6f4e017SAgata Olender getTransferProtocolFromUri(const std::string& imageUri) 323c6f4e017SAgata Olender { 3249e319cf0SAnna Platash try 3259e319cf0SAnna Platash { 3269e319cf0SAnna Platash std::string_view scheme = boost::urls::url_view(imageUri).scheme(); 3279e319cf0SAnna Platash if (scheme == "smb") 328c6f4e017SAgata Olender { 329c6f4e017SAgata Olender return TransferProtocol::smb; 330c6f4e017SAgata Olender } 33181ce609eSEd Tanous if (scheme == "https") 332c6f4e017SAgata Olender { 333c6f4e017SAgata Olender return TransferProtocol::https; 334c6f4e017SAgata Olender } 3359e319cf0SAnna Platash else if (!scheme.empty()) 336c6f4e017SAgata Olender { 337c6f4e017SAgata Olender return TransferProtocol::invalid; 338c6f4e017SAgata Olender } 339c6f4e017SAgata Olender } 3409e319cf0SAnna Platash catch (std::exception& p) 3419e319cf0SAnna Platash { 3429e319cf0SAnna Platash BMCWEB_LOG_ERROR << p.what(); 3439e319cf0SAnna Platash } 3449e319cf0SAnna Platash 3459e319cf0SAnna Platash return {}; 346c6f4e017SAgata Olender } 347c6f4e017SAgata Olender 348c6f4e017SAgata Olender /** 349c6f4e017SAgata Olender * @brief Function convert transfer protocol from string param. 350c6f4e017SAgata Olender * 351c6f4e017SAgata Olender */ 352c6f4e017SAgata Olender std::optional<TransferProtocol> getTransferProtocolFromParam( 353c6f4e017SAgata Olender const std::optional<std::string>& transferProtocolType) 354c6f4e017SAgata Olender { 355c6f4e017SAgata Olender if (transferProtocolType == std::nullopt) 356c6f4e017SAgata Olender { 357c6f4e017SAgata Olender return {}; 358c6f4e017SAgata Olender } 359c6f4e017SAgata Olender 360c6f4e017SAgata Olender if (*transferProtocolType == "CIFS") 361c6f4e017SAgata Olender { 362c6f4e017SAgata Olender return TransferProtocol::smb; 363c6f4e017SAgata Olender } 364c6f4e017SAgata Olender 365c6f4e017SAgata Olender if (*transferProtocolType == "HTTPS") 366c6f4e017SAgata Olender { 367c6f4e017SAgata Olender return TransferProtocol::https; 368c6f4e017SAgata Olender } 369c6f4e017SAgata Olender 370c6f4e017SAgata Olender return TransferProtocol::invalid; 371c6f4e017SAgata Olender } 372c6f4e017SAgata Olender 373c6f4e017SAgata Olender /** 374c6f4e017SAgata Olender * @brief Function extends URI with transfer protocol type. 375c6f4e017SAgata Olender * 376c6f4e017SAgata Olender */ 37781ce609eSEd Tanous std::string 378c6f4e017SAgata Olender getUriWithTransferProtocol(const std::string& imageUri, 379c6f4e017SAgata Olender const TransferProtocol& transferProtocol) 380c6f4e017SAgata Olender { 381c6f4e017SAgata Olender if (transferProtocol == TransferProtocol::smb) 382c6f4e017SAgata Olender { 383c6f4e017SAgata Olender return "smb://" + imageUri; 384c6f4e017SAgata Olender } 385c6f4e017SAgata Olender 386c6f4e017SAgata Olender if (transferProtocol == TransferProtocol::https) 387c6f4e017SAgata Olender { 388c6f4e017SAgata Olender return "https://" + imageUri; 389c6f4e017SAgata Olender } 390c6f4e017SAgata Olender 391c6f4e017SAgata Olender return imageUri; 392c6f4e017SAgata Olender } 393c6f4e017SAgata Olender 394c6f4e017SAgata Olender /** 395c6f4e017SAgata Olender * @brief Function validate parameters of insert media request. 396c6f4e017SAgata Olender * 397c6f4e017SAgata Olender */ 398*8d1b46d7Szhanghch05 bool validateParams(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 399*8d1b46d7Szhanghch05 std::string& imageUrl, 400c6f4e017SAgata Olender const std::optional<bool>& inserted, 401c6f4e017SAgata Olender const std::optional<std::string>& transferMethod, 402c6f4e017SAgata Olender const std::optional<std::string>& transferProtocolType) 403c6f4e017SAgata Olender { 404c6f4e017SAgata Olender BMCWEB_LOG_DEBUG << "Validation started"; 405c6f4e017SAgata Olender // required param imageUrl must not be empty 406c6f4e017SAgata Olender if (imageUrl.empty()) 407c6f4e017SAgata Olender { 408c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter Image is empty."; 409c6f4e017SAgata Olender 410*8d1b46d7Szhanghch05 messages::propertyValueFormatError(asyncResp->res, "<empty>", 411*8d1b46d7Szhanghch05 "Image"); 412c6f4e017SAgata Olender 413c6f4e017SAgata Olender return false; 414c6f4e017SAgata Olender } 415c6f4e017SAgata Olender 416c6f4e017SAgata Olender // optional param inserted must be true 417c6f4e017SAgata Olender if ((inserted != std::nullopt) && (*inserted != true)) 418c6f4e017SAgata Olender { 419c6f4e017SAgata Olender BMCWEB_LOG_ERROR 420c6f4e017SAgata Olender << "Request action optional parameter Inserted must be true."; 421c6f4e017SAgata Olender 422*8d1b46d7Szhanghch05 messages::actionParameterNotSupported(asyncResp->res, "Inserted", 423c6f4e017SAgata Olender "InsertMedia"); 424c6f4e017SAgata Olender 425c6f4e017SAgata Olender return false; 426c6f4e017SAgata Olender } 427c6f4e017SAgata Olender 428c6f4e017SAgata Olender // optional param transferMethod must be stream 429c6f4e017SAgata Olender if ((transferMethod != std::nullopt) && (*transferMethod != "Stream")) 430c6f4e017SAgata Olender { 431c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action optional parameter " 432c6f4e017SAgata Olender "TransferMethod must be Stream."; 433c6f4e017SAgata Olender 434*8d1b46d7Szhanghch05 messages::actionParameterNotSupported( 435*8d1b46d7Szhanghch05 asyncResp->res, "TransferMethod", "InsertMedia"); 436c6f4e017SAgata Olender 437c6f4e017SAgata Olender return false; 438c6f4e017SAgata Olender } 439c6f4e017SAgata Olender 440c6f4e017SAgata Olender std::optional<TransferProtocol> uriTransferProtocolType = 441c6f4e017SAgata Olender getTransferProtocolFromUri(imageUrl); 442c6f4e017SAgata Olender 443c6f4e017SAgata Olender std::optional<TransferProtocol> paramTransferProtocolType = 444c6f4e017SAgata Olender getTransferProtocolFromParam(transferProtocolType); 445c6f4e017SAgata Olender 446c6f4e017SAgata Olender // ImageUrl does not contain valid protocol type 447c6f4e017SAgata Olender if (*uriTransferProtocolType == TransferProtocol::invalid) 448c6f4e017SAgata Olender { 449c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must " 450c6f4e017SAgata Olender "contain specified protocol type from list: " 451c6f4e017SAgata Olender "(smb, https)."; 452c6f4e017SAgata Olender 453*8d1b46d7Szhanghch05 messages::resourceAtUriInUnknownFormat(asyncResp->res, imageUrl); 454c6f4e017SAgata Olender 455c6f4e017SAgata Olender return false; 456c6f4e017SAgata Olender } 457c6f4e017SAgata Olender 458c6f4e017SAgata Olender // transferProtocolType should contain value from list 459c6f4e017SAgata Olender if (*paramTransferProtocolType == TransferProtocol::invalid) 460c6f4e017SAgata Olender { 461c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType " 462c6f4e017SAgata Olender "must be provided with value from list: " 463c6f4e017SAgata Olender "(CIFS, HTTPS)."; 464c6f4e017SAgata Olender 465*8d1b46d7Szhanghch05 messages::propertyValueNotInList( 466*8d1b46d7Szhanghch05 asyncResp->res, *transferProtocolType, "TransferProtocolType"); 467c6f4e017SAgata Olender return false; 468c6f4e017SAgata Olender } 469c6f4e017SAgata Olender 470c6f4e017SAgata Olender // valid transfer protocol not provided either with URI nor param 471c6f4e017SAgata Olender if ((uriTransferProtocolType == std::nullopt) && 472c6f4e017SAgata Olender (paramTransferProtocolType == std::nullopt)) 473c6f4e017SAgata Olender { 474c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must " 475c6f4e017SAgata Olender "contain specified protocol type or param " 476c6f4e017SAgata Olender "TransferProtocolType must be provided."; 477c6f4e017SAgata Olender 478*8d1b46d7Szhanghch05 messages::resourceAtUriInUnknownFormat(asyncResp->res, imageUrl); 479c6f4e017SAgata Olender 480c6f4e017SAgata Olender return false; 481c6f4e017SAgata Olender } 482c6f4e017SAgata Olender 483c6f4e017SAgata Olender // valid transfer protocol provided both with URI and param 484c6f4e017SAgata Olender if ((paramTransferProtocolType != std::nullopt) && 485c6f4e017SAgata Olender (uriTransferProtocolType != std::nullopt)) 486c6f4e017SAgata Olender { 487c6f4e017SAgata Olender // check if protocol is the same for URI and param 488c6f4e017SAgata Olender if (*paramTransferProtocolType != *uriTransferProtocolType) 489c6f4e017SAgata Olender { 490c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter " 491c6f4e017SAgata Olender "TransferProtocolType must contain the " 492c6f4e017SAgata Olender "same protocol type as protocol type " 493c6f4e017SAgata Olender "provided with param imageUrl."; 494c6f4e017SAgata Olender 495c6f4e017SAgata Olender messages::actionParameterValueTypeError( 496*8d1b46d7Szhanghch05 asyncResp->res, *transferProtocolType, 497*8d1b46d7Szhanghch05 "TransferProtocolType", "InsertMedia"); 498c6f4e017SAgata Olender 499c6f4e017SAgata Olender return false; 500c6f4e017SAgata Olender } 501c6f4e017SAgata Olender } 502c6f4e017SAgata Olender 503c6f4e017SAgata Olender // validation passed 504c6f4e017SAgata Olender // add protocol to URI if needed 505c6f4e017SAgata Olender if (uriTransferProtocolType == std::nullopt) 506c6f4e017SAgata Olender { 507c6f4e017SAgata Olender imageUrl = getUriWithTransferProtocol(imageUrl, 508c6f4e017SAgata Olender *paramTransferProtocolType); 509c6f4e017SAgata Olender } 510c6f4e017SAgata Olender 511c6f4e017SAgata Olender return true; 512c6f4e017SAgata Olender } 513c6f4e017SAgata Olender 514c6f4e017SAgata Olender /** 515e13c2760SPrzemyslaw Czarnowski * @brief Function handles POST method request. 516e13c2760SPrzemyslaw Czarnowski * 517e13c2760SPrzemyslaw Czarnowski * Analyzes POST body message before sends Reset request data to dbus. 518e13c2760SPrzemyslaw Czarnowski */ 519*8d1b46d7Szhanghch05 void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 520*8d1b46d7Szhanghch05 const crow::Request& req, 521e13c2760SPrzemyslaw Czarnowski const std::vector<std::string>& params) override 522e13c2760SPrzemyslaw Czarnowski { 523e13c2760SPrzemyslaw Czarnowski if (params.size() != 2) 524e13c2760SPrzemyslaw Czarnowski { 525*8d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 526e13c2760SPrzemyslaw Czarnowski return; 527e13c2760SPrzemyslaw Czarnowski } 528e13c2760SPrzemyslaw Czarnowski 529e13c2760SPrzemyslaw Czarnowski // take resource name from URL 530e13c2760SPrzemyslaw Czarnowski const std::string& resName = params[1]; 531e13c2760SPrzemyslaw Czarnowski 532e13c2760SPrzemyslaw Czarnowski if (params[0] != "bmc") 533e13c2760SPrzemyslaw Czarnowski { 534*8d1b46d7Szhanghch05 messages::resourceNotFound(asyncResp->res, "VirtualMedia.Insert", 535*8d1b46d7Szhanghch05 resName); 536e13c2760SPrzemyslaw Czarnowski 537e13c2760SPrzemyslaw Czarnowski return; 538e13c2760SPrzemyslaw Czarnowski } 539e13c2760SPrzemyslaw Czarnowski 540e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 541*8d1b46d7Szhanghch05 [this, asyncResp, req, 542e13c2760SPrzemyslaw Czarnowski resName](const boost::system::error_code ec, 543e13c2760SPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 544e13c2760SPrzemyslaw Czarnowski if (ec) 545e13c2760SPrzemyslaw Czarnowski { 546e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 547e13c2760SPrzemyslaw Czarnowski << ec; 548*8d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 549e13c2760SPrzemyslaw Czarnowski 550e13c2760SPrzemyslaw Czarnowski return; 551e13c2760SPrzemyslaw Czarnowski } 552e13c2760SPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 553e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 554e13c2760SPrzemyslaw Czarnowski 555e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 55681ce609eSEd Tanous [this, service, resName, req, 557*8d1b46d7Szhanghch05 asyncResp](const boost::system::error_code ec, 558e13c2760SPrzemyslaw Czarnowski ManagedObjectType& subtree) { 559e13c2760SPrzemyslaw Czarnowski if (ec) 560e13c2760SPrzemyslaw Czarnowski { 561e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 562e13c2760SPrzemyslaw Czarnowski 563e13c2760SPrzemyslaw Czarnowski return; 564e13c2760SPrzemyslaw Czarnowski } 565e13c2760SPrzemyslaw Czarnowski 566e13c2760SPrzemyslaw Czarnowski for (const auto& object : subtree) 567e13c2760SPrzemyslaw Czarnowski { 568e13c2760SPrzemyslaw Czarnowski const std::string& path = 569e13c2760SPrzemyslaw Czarnowski static_cast<const std::string&>(object.first); 570e13c2760SPrzemyslaw Czarnowski 571f23b7296SEd Tanous std::size_t lastIndex = path.rfind('/'); 572e13c2760SPrzemyslaw Czarnowski if (lastIndex == std::string::npos) 573e13c2760SPrzemyslaw Czarnowski { 574e13c2760SPrzemyslaw Czarnowski continue; 575e13c2760SPrzemyslaw Czarnowski } 576e13c2760SPrzemyslaw Czarnowski 577e13c2760SPrzemyslaw Czarnowski lastIndex += 1; 578e13c2760SPrzemyslaw Czarnowski 579e13c2760SPrzemyslaw Czarnowski if (path.substr(lastIndex) == resName) 580e13c2760SPrzemyslaw Czarnowski { 581e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Proxy"); 582e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 583e13c2760SPrzemyslaw Czarnowski { 584e13c2760SPrzemyslaw Czarnowski // Not possible in proxy mode 585e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "InsertMedia not " 586e13c2760SPrzemyslaw Czarnowski "allowed in proxy mode"; 587e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound( 588*8d1b46d7Szhanghch05 asyncResp->res, 589*8d1b46d7Szhanghch05 "VirtualMedia.InsertMedia", resName); 590e13c2760SPrzemyslaw Czarnowski 591e13c2760SPrzemyslaw Czarnowski return; 592e13c2760SPrzemyslaw Czarnowski } 593e13c2760SPrzemyslaw Czarnowski 594e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Legacy"); 595c6f4e017SAgata Olender if (lastIndex == std::string::npos) 596e13c2760SPrzemyslaw Czarnowski { 597c6f4e017SAgata Olender continue; 598c6f4e017SAgata Olender } 599c6f4e017SAgata Olender 600e13c2760SPrzemyslaw Czarnowski // Legacy mode 601e13c2760SPrzemyslaw Czarnowski std::string imageUrl; 602c6f4e017SAgata Olender std::optional<std::string> userName; 603c6f4e017SAgata Olender std::optional<std::string> password; 604c6f4e017SAgata Olender std::optional<std::string> transferMethod; 605c6f4e017SAgata Olender std::optional<std::string> transferProtocolType; 606c6f4e017SAgata Olender std::optional<bool> writeProtected = true; 607c6f4e017SAgata Olender std::optional<bool> inserted; 608e13c2760SPrzemyslaw Czarnowski 6094e0453b1SGunnar Mills // Read obligatory parameters (url of image) 610d6da5bebSAdrian Ambrożewicz if (!json_util::readJson( 611*8d1b46d7Szhanghch05 req, asyncResp->res, "Image", imageUrl, 612988fb7b2SAdrian Ambrożewicz "WriteProtected", writeProtected, 613988fb7b2SAdrian Ambrożewicz "UserName", userName, "Password", 614c6f4e017SAgata Olender password, "Inserted", inserted, 615c6f4e017SAgata Olender "TransferMethod", transferMethod, 616c6f4e017SAgata Olender "TransferProtocolType", 617c6f4e017SAgata Olender transferProtocolType)) 618e13c2760SPrzemyslaw Czarnowski { 619c6f4e017SAgata Olender BMCWEB_LOG_DEBUG << "Image is not provided"; 620e13c2760SPrzemyslaw Czarnowski return; 621e13c2760SPrzemyslaw Czarnowski } 622e13c2760SPrzemyslaw Czarnowski 623c6f4e017SAgata Olender bool paramsValid = validateParams( 624*8d1b46d7Szhanghch05 asyncResp->res, imageUrl, inserted, 625c6f4e017SAgata Olender transferMethod, transferProtocolType); 626c6f4e017SAgata Olender 627c6f4e017SAgata Olender if (paramsValid == false) 628e13c2760SPrzemyslaw Czarnowski { 629e13c2760SPrzemyslaw Czarnowski return; 630e13c2760SPrzemyslaw Czarnowski } 631e13c2760SPrzemyslaw Czarnowski 632c6f4e017SAgata Olender // manager is irrelevant for VirtualMedia dbus 633c6f4e017SAgata Olender // calls 634*8d1b46d7Szhanghch05 doMountVmLegacy(asyncResp, service, resName, 635c6f4e017SAgata Olender imageUrl, !(*writeProtected), 63681ce609eSEd Tanous std::move(*userName), 63781ce609eSEd Tanous std::move(*password)); 638e13c2760SPrzemyslaw Czarnowski 639e13c2760SPrzemyslaw Czarnowski return; 640e13c2760SPrzemyslaw Czarnowski } 641e13c2760SPrzemyslaw Czarnowski } 642e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Parent item not found"; 643*8d1b46d7Szhanghch05 messages::resourceNotFound(asyncResp->res, 644*8d1b46d7Szhanghch05 "VirtualMedia", resName); 645e13c2760SPrzemyslaw Czarnowski }, 646e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 647e13c2760SPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 648e13c2760SPrzemyslaw Czarnowski }, 649e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 650e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 651e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 652e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 653e13c2760SPrzemyslaw Czarnowski } 654e13c2760SPrzemyslaw Czarnowski 6551214b7e7SGunnar Mills template <typename T> 6561214b7e7SGunnar Mills static void secureCleanup(T& value) 657988fb7b2SAdrian Ambrożewicz { 658988fb7b2SAdrian Ambrożewicz auto raw = const_cast<typename T::value_type*>(value.data()); 659988fb7b2SAdrian Ambrożewicz explicit_bzero(raw, value.size() * sizeof(*raw)); 660988fb7b2SAdrian Ambrożewicz } 661988fb7b2SAdrian Ambrożewicz 662988fb7b2SAdrian Ambrożewicz class Credentials 663988fb7b2SAdrian Ambrożewicz { 664988fb7b2SAdrian Ambrożewicz public: 665988fb7b2SAdrian Ambrożewicz Credentials(std::string&& user, std::string&& password) : 666988fb7b2SAdrian Ambrożewicz userBuf(std::move(user)), passBuf(std::move(password)) 6671214b7e7SGunnar Mills {} 668988fb7b2SAdrian Ambrożewicz 669988fb7b2SAdrian Ambrożewicz ~Credentials() 670988fb7b2SAdrian Ambrożewicz { 671988fb7b2SAdrian Ambrożewicz secureCleanup(userBuf); 672988fb7b2SAdrian Ambrożewicz secureCleanup(passBuf); 673988fb7b2SAdrian Ambrożewicz } 674988fb7b2SAdrian Ambrożewicz 675988fb7b2SAdrian Ambrożewicz const std::string& user() 676988fb7b2SAdrian Ambrożewicz { 677988fb7b2SAdrian Ambrożewicz return userBuf; 678988fb7b2SAdrian Ambrożewicz } 679988fb7b2SAdrian Ambrożewicz 680988fb7b2SAdrian Ambrożewicz const std::string& password() 681988fb7b2SAdrian Ambrożewicz { 682988fb7b2SAdrian Ambrożewicz return passBuf; 683988fb7b2SAdrian Ambrożewicz } 684988fb7b2SAdrian Ambrożewicz 685988fb7b2SAdrian Ambrożewicz private: 686988fb7b2SAdrian Ambrożewicz Credentials() = delete; 687988fb7b2SAdrian Ambrożewicz Credentials(const Credentials&) = delete; 688988fb7b2SAdrian Ambrożewicz Credentials& operator=(const Credentials&) = delete; 689988fb7b2SAdrian Ambrożewicz 690988fb7b2SAdrian Ambrożewicz std::string userBuf; 691988fb7b2SAdrian Ambrożewicz std::string passBuf; 692988fb7b2SAdrian Ambrożewicz }; 693988fb7b2SAdrian Ambrożewicz 694988fb7b2SAdrian Ambrożewicz class CredentialsProvider 695988fb7b2SAdrian Ambrożewicz { 696988fb7b2SAdrian Ambrożewicz public: 6971214b7e7SGunnar Mills template <typename T> 6981214b7e7SGunnar Mills struct Deleter 699988fb7b2SAdrian Ambrożewicz { 700988fb7b2SAdrian Ambrożewicz void operator()(T* buff) const 701988fb7b2SAdrian Ambrożewicz { 702988fb7b2SAdrian Ambrożewicz if (buff) 703988fb7b2SAdrian Ambrożewicz { 704988fb7b2SAdrian Ambrożewicz secureCleanup(*buff); 705988fb7b2SAdrian Ambrożewicz delete buff; 706988fb7b2SAdrian Ambrożewicz } 707988fb7b2SAdrian Ambrożewicz } 708988fb7b2SAdrian Ambrożewicz }; 709988fb7b2SAdrian Ambrożewicz 710988fb7b2SAdrian Ambrożewicz using Buffer = std::vector<char>; 711988fb7b2SAdrian Ambrożewicz using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>; 712988fb7b2SAdrian Ambrożewicz // Using explicit definition instead of std::function to avoid implicit 713988fb7b2SAdrian Ambrożewicz // conversions eg. stack copy instead of reference 714988fb7b2SAdrian Ambrożewicz using FormatterFunc = void(const std::string& username, 715988fb7b2SAdrian Ambrożewicz const std::string& password, Buffer& dest); 716988fb7b2SAdrian Ambrożewicz 717988fb7b2SAdrian Ambrożewicz CredentialsProvider(std::string&& user, std::string&& password) : 718988fb7b2SAdrian Ambrożewicz credentials(std::move(user), std::move(password)) 7191214b7e7SGunnar Mills {} 720988fb7b2SAdrian Ambrożewicz 721988fb7b2SAdrian Ambrożewicz const std::string& user() 722988fb7b2SAdrian Ambrożewicz { 723988fb7b2SAdrian Ambrożewicz return credentials.user(); 724988fb7b2SAdrian Ambrożewicz } 725988fb7b2SAdrian Ambrożewicz 726988fb7b2SAdrian Ambrożewicz const std::string& password() 727988fb7b2SAdrian Ambrożewicz { 728988fb7b2SAdrian Ambrożewicz return credentials.password(); 729988fb7b2SAdrian Ambrożewicz } 730988fb7b2SAdrian Ambrożewicz 73181ce609eSEd Tanous SecureBuffer pack(FormatterFunc formatter) 732988fb7b2SAdrian Ambrożewicz { 733988fb7b2SAdrian Ambrożewicz SecureBuffer packed{new Buffer{}}; 734988fb7b2SAdrian Ambrożewicz if (formatter) 735988fb7b2SAdrian Ambrożewicz { 736988fb7b2SAdrian Ambrożewicz formatter(credentials.user(), credentials.password(), *packed); 737988fb7b2SAdrian Ambrożewicz } 738988fb7b2SAdrian Ambrożewicz 739988fb7b2SAdrian Ambrożewicz return packed; 740988fb7b2SAdrian Ambrożewicz } 741988fb7b2SAdrian Ambrożewicz 742988fb7b2SAdrian Ambrożewicz private: 743988fb7b2SAdrian Ambrożewicz Credentials credentials; 744988fb7b2SAdrian Ambrożewicz }; 745988fb7b2SAdrian Ambrożewicz 746988fb7b2SAdrian Ambrożewicz // Wrapper for boost::async_pipe ensuring proper pipe cleanup 7471214b7e7SGunnar Mills template <typename Buffer> 7481214b7e7SGunnar Mills class Pipe 749988fb7b2SAdrian Ambrożewicz { 750988fb7b2SAdrian Ambrożewicz public: 751988fb7b2SAdrian Ambrożewicz using unix_fd = sdbusplus::message::unix_fd; 752988fb7b2SAdrian Ambrożewicz 753988fb7b2SAdrian Ambrożewicz Pipe(boost::asio::io_context& io, Buffer&& buffer) : 754988fb7b2SAdrian Ambrożewicz impl(io), buffer{std::move(buffer)} 7551214b7e7SGunnar Mills {} 756988fb7b2SAdrian Ambrożewicz 757988fb7b2SAdrian Ambrożewicz ~Pipe() 758988fb7b2SAdrian Ambrożewicz { 759988fb7b2SAdrian Ambrożewicz // Named pipe needs to be explicitly removed 760988fb7b2SAdrian Ambrożewicz impl.close(); 761988fb7b2SAdrian Ambrożewicz } 762988fb7b2SAdrian Ambrożewicz 763988fb7b2SAdrian Ambrożewicz unix_fd fd() 764988fb7b2SAdrian Ambrożewicz { 765988fb7b2SAdrian Ambrożewicz return unix_fd{impl.native_source()}; 766988fb7b2SAdrian Ambrożewicz } 767988fb7b2SAdrian Ambrożewicz 768988fb7b2SAdrian Ambrożewicz template <typename WriteHandler> 76981ce609eSEd Tanous void asyncWrite(WriteHandler&& handler) 770988fb7b2SAdrian Ambrożewicz { 771988fb7b2SAdrian Ambrożewicz impl.async_write_some(data(), std::forward<WriteHandler>(handler)); 772988fb7b2SAdrian Ambrożewicz } 773988fb7b2SAdrian Ambrożewicz 774988fb7b2SAdrian Ambrożewicz private: 775988fb7b2SAdrian Ambrożewicz // Specialization for pointer types 776988fb7b2SAdrian Ambrożewicz template <typename B = Buffer> 777988fb7b2SAdrian Ambrożewicz typename std::enable_if<boost::has_dereference<B>::value, 778988fb7b2SAdrian Ambrożewicz boost::asio::const_buffer>::type 779988fb7b2SAdrian Ambrożewicz data() 780988fb7b2SAdrian Ambrożewicz { 781988fb7b2SAdrian Ambrożewicz return boost::asio::buffer(*buffer); 782988fb7b2SAdrian Ambrożewicz } 783988fb7b2SAdrian Ambrożewicz 784988fb7b2SAdrian Ambrożewicz template <typename B = Buffer> 785988fb7b2SAdrian Ambrożewicz typename std::enable_if<!boost::has_dereference<B>::value, 786988fb7b2SAdrian Ambrożewicz boost::asio::const_buffer>::type 787988fb7b2SAdrian Ambrożewicz data() 788988fb7b2SAdrian Ambrożewicz { 789988fb7b2SAdrian Ambrożewicz return boost::asio::buffer(buffer); 790988fb7b2SAdrian Ambrożewicz } 791988fb7b2SAdrian Ambrożewicz 792988fb7b2SAdrian Ambrożewicz const std::string name; 793988fb7b2SAdrian Ambrożewicz boost::process::async_pipe impl; 794988fb7b2SAdrian Ambrożewicz Buffer buffer; 795988fb7b2SAdrian Ambrożewicz }; 796988fb7b2SAdrian Ambrożewicz 797e13c2760SPrzemyslaw Czarnowski /** 798e13c2760SPrzemyslaw Czarnowski * @brief Function transceives data with dbus directly. 799e13c2760SPrzemyslaw Czarnowski * 800e13c2760SPrzemyslaw Czarnowski * All BMC state properties will be retrieved before sending reset request. 801e13c2760SPrzemyslaw Czarnowski */ 802*8d1b46d7Szhanghch05 void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 803e13c2760SPrzemyslaw Czarnowski const std::string& service, const std::string& name, 804988fb7b2SAdrian Ambrożewicz const std::string& imageUrl, const bool rw, 805988fb7b2SAdrian Ambrożewicz std::string&& userName, std::string&& password) 806e13c2760SPrzemyslaw Czarnowski { 807988fb7b2SAdrian Ambrożewicz using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>; 808988fb7b2SAdrian Ambrożewicz constexpr const size_t secretLimit = 1024; 809988fb7b2SAdrian Ambrożewicz 810988fb7b2SAdrian Ambrożewicz std::shared_ptr<SecurePipe> secretPipe; 811988fb7b2SAdrian Ambrożewicz std::variant<int, SecurePipe::unix_fd> unixFd = -1; 812988fb7b2SAdrian Ambrożewicz 813988fb7b2SAdrian Ambrożewicz if (!userName.empty() || !password.empty()) 814988fb7b2SAdrian Ambrożewicz { 815988fb7b2SAdrian Ambrożewicz // Encapsulate in safe buffer 816988fb7b2SAdrian Ambrożewicz CredentialsProvider credentials(std::move(userName), 817988fb7b2SAdrian Ambrożewicz std::move(password)); 818988fb7b2SAdrian Ambrożewicz 819988fb7b2SAdrian Ambrożewicz // Payload must contain data + NULL delimiters 820988fb7b2SAdrian Ambrożewicz if (credentials.user().size() + credentials.password().size() + 2 > 821988fb7b2SAdrian Ambrożewicz secretLimit) 822988fb7b2SAdrian Ambrożewicz { 823988fb7b2SAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Credentials too long to handle"; 824988fb7b2SAdrian Ambrożewicz messages::unrecognizedRequestBody(asyncResp->res); 825988fb7b2SAdrian Ambrożewicz return; 826988fb7b2SAdrian Ambrożewicz } 827988fb7b2SAdrian Ambrożewicz 828988fb7b2SAdrian Ambrożewicz // Pack secret 829988fb7b2SAdrian Ambrożewicz auto secret = credentials.pack([](const auto& user, 830988fb7b2SAdrian Ambrożewicz const auto& pass, auto& buff) { 831988fb7b2SAdrian Ambrożewicz std::copy(user.begin(), user.end(), std::back_inserter(buff)); 832988fb7b2SAdrian Ambrożewicz buff.push_back('\0'); 833988fb7b2SAdrian Ambrożewicz std::copy(pass.begin(), pass.end(), std::back_inserter(buff)); 834988fb7b2SAdrian Ambrożewicz buff.push_back('\0'); 835988fb7b2SAdrian Ambrożewicz }); 836988fb7b2SAdrian Ambrożewicz 837988fb7b2SAdrian Ambrożewicz // Open pipe 838988fb7b2SAdrian Ambrożewicz secretPipe = std::make_shared<SecurePipe>( 839988fb7b2SAdrian Ambrożewicz crow::connections::systemBus->get_io_context(), 840988fb7b2SAdrian Ambrożewicz std::move(secret)); 841988fb7b2SAdrian Ambrożewicz unixFd = secretPipe->fd(); 842988fb7b2SAdrian Ambrożewicz 843988fb7b2SAdrian Ambrożewicz // Pass secret over pipe 84481ce609eSEd Tanous secretPipe->asyncWrite( 845f5b16f03SVikram Bodireddy [asyncResp](const boost::system::error_code& ec, std::size_t) { 846988fb7b2SAdrian Ambrożewicz if (ec) 847988fb7b2SAdrian Ambrożewicz { 848988fb7b2SAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec; 849988fb7b2SAdrian Ambrożewicz messages::internalError(asyncResp->res); 850988fb7b2SAdrian Ambrożewicz } 851988fb7b2SAdrian Ambrożewicz }); 852988fb7b2SAdrian Ambrożewicz } 853988fb7b2SAdrian Ambrożewicz 854e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 855988fb7b2SAdrian Ambrożewicz [asyncResp, secretPipe](const boost::system::error_code ec, 856988fb7b2SAdrian Ambrożewicz bool success) { 857e13c2760SPrzemyslaw Czarnowski if (ec) 858e13c2760SPrzemyslaw Czarnowski { 859e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 860e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 861d6da5bebSAdrian Ambrożewicz } 862d6da5bebSAdrian Ambrożewicz else if (!success) 863d6da5bebSAdrian Ambrożewicz { 864d6da5bebSAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Service responded with error"; 865d6da5bebSAdrian Ambrożewicz messages::generalError(asyncResp->res); 866e13c2760SPrzemyslaw Czarnowski } 867e13c2760SPrzemyslaw Czarnowski }, 868e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, 869988fb7b2SAdrian Ambrożewicz "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw, 870988fb7b2SAdrian Ambrożewicz unixFd); 871e13c2760SPrzemyslaw Czarnowski } 872e13c2760SPrzemyslaw Czarnowski }; 873e13c2760SPrzemyslaw Czarnowski 874e13c2760SPrzemyslaw Czarnowski /** 875e13c2760SPrzemyslaw Czarnowski @brief EjectMedia action class 876e13c2760SPrzemyslaw Czarnowski */ 877e13c2760SPrzemyslaw Czarnowski class VirtualMediaActionEjectMedia : public Node 878e13c2760SPrzemyslaw Czarnowski { 879e13c2760SPrzemyslaw Czarnowski public: 88052cc112dSEd Tanous VirtualMediaActionEjectMedia(App& app) : 881e13c2760SPrzemyslaw Czarnowski Node(app, 882e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/" 883e13c2760SPrzemyslaw Czarnowski "VirtualMedia.EjectMedia", 884e13c2760SPrzemyslaw Czarnowski std::string(), std::string()) 885e13c2760SPrzemyslaw Czarnowski { 886e13c2760SPrzemyslaw Czarnowski entityPrivileges = { 887e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 888e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 889e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 890e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 891e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 892e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 893e13c2760SPrzemyslaw Czarnowski } 894e13c2760SPrzemyslaw Czarnowski 895e13c2760SPrzemyslaw Czarnowski private: 896e13c2760SPrzemyslaw Czarnowski /** 897e13c2760SPrzemyslaw Czarnowski * @brief Function handles POST method request. 898e13c2760SPrzemyslaw Czarnowski * 899e13c2760SPrzemyslaw Czarnowski * Analyzes POST body message before sends Reset request data to dbus. 900e13c2760SPrzemyslaw Czarnowski */ 901*8d1b46d7Szhanghch05 void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 902*8d1b46d7Szhanghch05 const crow::Request& req, 903e13c2760SPrzemyslaw Czarnowski const std::vector<std::string>& params) override 904e13c2760SPrzemyslaw Czarnowski { 905e13c2760SPrzemyslaw Czarnowski if (params.size() != 2) 906e13c2760SPrzemyslaw Czarnowski { 907*8d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 908e13c2760SPrzemyslaw Czarnowski return; 909e13c2760SPrzemyslaw Czarnowski } 910e13c2760SPrzemyslaw Czarnowski 911e13c2760SPrzemyslaw Czarnowski // take resource name from URL 912e13c2760SPrzemyslaw Czarnowski const std::string& resName = params[1]; 913e13c2760SPrzemyslaw Czarnowski 914e13c2760SPrzemyslaw Czarnowski if (params[0] != "bmc") 915e13c2760SPrzemyslaw Czarnowski { 916*8d1b46d7Szhanghch05 messages::resourceNotFound(asyncResp->res, "VirtualMedia.Eject", 917*8d1b46d7Szhanghch05 resName); 918e13c2760SPrzemyslaw Czarnowski 919e13c2760SPrzemyslaw Czarnowski return; 920e13c2760SPrzemyslaw Czarnowski } 921e13c2760SPrzemyslaw Czarnowski 922e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 923*8d1b46d7Szhanghch05 [this, asyncResp{std::move(asyncResp)}, req, 924e13c2760SPrzemyslaw Czarnowski resName](const boost::system::error_code ec, 925e13c2760SPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 926e13c2760SPrzemyslaw Czarnowski if (ec) 927e13c2760SPrzemyslaw Czarnowski { 928e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 929e13c2760SPrzemyslaw Czarnowski << ec; 930*8d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 931e13c2760SPrzemyslaw Czarnowski 932e13c2760SPrzemyslaw Czarnowski return; 933e13c2760SPrzemyslaw Czarnowski } 934e13c2760SPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 935e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 936e13c2760SPrzemyslaw Czarnowski 937e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 93881ce609eSEd Tanous [this, resName, service, req, 939*8d1b46d7Szhanghch05 asyncResp{asyncResp}](const boost::system::error_code ec, 940e13c2760SPrzemyslaw Czarnowski ManagedObjectType& subtree) { 941e13c2760SPrzemyslaw Czarnowski if (ec) 942e13c2760SPrzemyslaw Czarnowski { 943e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 944e13c2760SPrzemyslaw Czarnowski 945e13c2760SPrzemyslaw Czarnowski return; 946e13c2760SPrzemyslaw Czarnowski } 947e13c2760SPrzemyslaw Czarnowski 948e13c2760SPrzemyslaw Czarnowski for (const auto& object : subtree) 949e13c2760SPrzemyslaw Czarnowski { 950e13c2760SPrzemyslaw Czarnowski const std::string& path = 951e13c2760SPrzemyslaw Czarnowski static_cast<const std::string&>(object.first); 952e13c2760SPrzemyslaw Czarnowski 953f23b7296SEd Tanous std::size_t lastIndex = path.rfind('/'); 954e13c2760SPrzemyslaw Czarnowski if (lastIndex == std::string::npos) 955e13c2760SPrzemyslaw Czarnowski { 956e13c2760SPrzemyslaw Czarnowski continue; 957e13c2760SPrzemyslaw Czarnowski } 958e13c2760SPrzemyslaw Czarnowski 959e13c2760SPrzemyslaw Czarnowski lastIndex += 1; 960e13c2760SPrzemyslaw Czarnowski 961e13c2760SPrzemyslaw Czarnowski if (path.substr(lastIndex) == resName) 962e13c2760SPrzemyslaw Czarnowski { 963e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Proxy"); 964e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 965e13c2760SPrzemyslaw Czarnowski { 966e13c2760SPrzemyslaw Czarnowski // Proxy mode 967*8d1b46d7Szhanghch05 doVmAction(asyncResp, service, resName, 968*8d1b46d7Szhanghch05 false); 969e13c2760SPrzemyslaw Czarnowski } 970e13c2760SPrzemyslaw Czarnowski 971e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Legacy"); 972e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 973e13c2760SPrzemyslaw Czarnowski { 974e13c2760SPrzemyslaw Czarnowski // Legacy mode 975*8d1b46d7Szhanghch05 doVmAction(asyncResp, service, resName, 976*8d1b46d7Szhanghch05 true); 977e13c2760SPrzemyslaw Czarnowski } 978e13c2760SPrzemyslaw Czarnowski 979e13c2760SPrzemyslaw Czarnowski return; 980e13c2760SPrzemyslaw Czarnowski } 981e13c2760SPrzemyslaw Czarnowski } 982e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Parent item not found"; 983*8d1b46d7Szhanghch05 messages::resourceNotFound(asyncResp->res, 984*8d1b46d7Szhanghch05 "VirtualMedia", resName); 985e13c2760SPrzemyslaw Czarnowski }, 986e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 987e13c2760SPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 988e13c2760SPrzemyslaw Czarnowski }, 989e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 990e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 991e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 992e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 993e13c2760SPrzemyslaw Czarnowski } 994e13c2760SPrzemyslaw Czarnowski 995e13c2760SPrzemyslaw Czarnowski /** 996e13c2760SPrzemyslaw Czarnowski * @brief Function transceives data with dbus directly. 997e13c2760SPrzemyslaw Czarnowski * 998e13c2760SPrzemyslaw Czarnowski * All BMC state properties will be retrieved before sending reset request. 999e13c2760SPrzemyslaw Czarnowski */ 1000*8d1b46d7Szhanghch05 void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1001e13c2760SPrzemyslaw Czarnowski const std::string& service, const std::string& name, 1002e13c2760SPrzemyslaw Czarnowski bool legacy) 1003e13c2760SPrzemyslaw Czarnowski { 1004e13c2760SPrzemyslaw Czarnowski 1005e13c2760SPrzemyslaw Czarnowski // Legacy mount requires parameter with image 1006e13c2760SPrzemyslaw Czarnowski if (legacy) 1007e13c2760SPrzemyslaw Czarnowski { 1008e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1009e13c2760SPrzemyslaw Czarnowski [asyncResp](const boost::system::error_code ec) { 1010e13c2760SPrzemyslaw Czarnowski if (ec) 1011e13c2760SPrzemyslaw Czarnowski { 1012e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 1013e13c2760SPrzemyslaw Czarnowski 1014e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1015e13c2760SPrzemyslaw Czarnowski return; 1016e13c2760SPrzemyslaw Czarnowski } 1017e13c2760SPrzemyslaw Czarnowski }, 1018e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, 1019e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount"); 1020e13c2760SPrzemyslaw Czarnowski } 1021e13c2760SPrzemyslaw Czarnowski else // proxy 1022e13c2760SPrzemyslaw Czarnowski { 1023e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1024e13c2760SPrzemyslaw Czarnowski [asyncResp](const boost::system::error_code ec) { 1025e13c2760SPrzemyslaw Czarnowski if (ec) 1026e13c2760SPrzemyslaw Czarnowski { 1027e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 1028e13c2760SPrzemyslaw Czarnowski 1029e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1030e13c2760SPrzemyslaw Czarnowski return; 1031e13c2760SPrzemyslaw Czarnowski } 1032e13c2760SPrzemyslaw Czarnowski }, 1033e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name, 1034e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount"); 1035e13c2760SPrzemyslaw Czarnowski } 1036e13c2760SPrzemyslaw Czarnowski } 1037e13c2760SPrzemyslaw Czarnowski }; 1038e13c2760SPrzemyslaw Czarnowski 1039107077deSPrzemyslaw Czarnowski class VirtualMediaCollection : public Node 1040107077deSPrzemyslaw Czarnowski { 1041107077deSPrzemyslaw Czarnowski public: 1042107077deSPrzemyslaw Czarnowski /* 1043107077deSPrzemyslaw Czarnowski * Default Constructor 1044107077deSPrzemyslaw Czarnowski */ 104552cc112dSEd Tanous VirtualMediaCollection(App& app) : 1046107077deSPrzemyslaw Czarnowski Node(app, "/redfish/v1/Managers/<str>/VirtualMedia/", std::string()) 1047107077deSPrzemyslaw Czarnowski { 1048107077deSPrzemyslaw Czarnowski entityPrivileges = { 1049107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 1050107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 1051107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 1052107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 1053107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 1054107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 1055107077deSPrzemyslaw Czarnowski } 1056107077deSPrzemyslaw Czarnowski 1057107077deSPrzemyslaw Czarnowski private: 1058107077deSPrzemyslaw Czarnowski /** 1059107077deSPrzemyslaw Czarnowski * Functions triggers appropriate requests on DBus 1060107077deSPrzemyslaw Czarnowski */ 1061*8d1b46d7Szhanghch05 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1062*8d1b46d7Szhanghch05 const crow::Request&, 1063107077deSPrzemyslaw Czarnowski const std::vector<std::string>& params) override 1064107077deSPrzemyslaw Czarnowski { 1065107077deSPrzemyslaw Czarnowski 1066107077deSPrzemyslaw Czarnowski // Check if there is required param, truly entering this shall be 1067107077deSPrzemyslaw Czarnowski // impossible 1068107077deSPrzemyslaw Czarnowski if (params.size() != 1) 1069107077deSPrzemyslaw Czarnowski { 1070*8d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 1071107077deSPrzemyslaw Czarnowski 1072107077deSPrzemyslaw Czarnowski return; 1073107077deSPrzemyslaw Czarnowski } 1074107077deSPrzemyslaw Czarnowski 1075107077deSPrzemyslaw Czarnowski const std::string& name = params[0]; 1076107077deSPrzemyslaw Czarnowski 1077107077deSPrzemyslaw Czarnowski if (name != "bmc") 1078107077deSPrzemyslaw Czarnowski { 1079107077deSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, "VirtualMedia", name); 1080107077deSPrzemyslaw Czarnowski 1081107077deSPrzemyslaw Czarnowski return; 1082107077deSPrzemyslaw Czarnowski } 1083107077deSPrzemyslaw Czarnowski 1084*8d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1085107077deSPrzemyslaw Czarnowski "#VirtualMediaCollection.VirtualMediaCollection"; 1086*8d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Virtual Media Services"; 1087*8d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 1088d6c414f3SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia"; 1089107077deSPrzemyslaw Czarnowski 1090107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1091107077deSPrzemyslaw Czarnowski [asyncResp, name](const boost::system::error_code ec, 1092107077deSPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 1093107077deSPrzemyslaw Czarnowski if (ec) 1094107077deSPrzemyslaw Czarnowski { 1095107077deSPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 1096107077deSPrzemyslaw Czarnowski << ec; 1097107077deSPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1098107077deSPrzemyslaw Czarnowski 1099107077deSPrzemyslaw Czarnowski return; 1100107077deSPrzemyslaw Czarnowski } 1101107077deSPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 1102107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 1103107077deSPrzemyslaw Czarnowski 1104107077deSPrzemyslaw Czarnowski getVmResourceList(asyncResp, service, name); 1105107077deSPrzemyslaw Czarnowski }, 1106107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 1107107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 1108107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 1109107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 1110107077deSPrzemyslaw Czarnowski } 1111107077deSPrzemyslaw Czarnowski }; 1112107077deSPrzemyslaw Czarnowski 1113107077deSPrzemyslaw Czarnowski class VirtualMedia : public Node 1114107077deSPrzemyslaw Czarnowski { 1115107077deSPrzemyslaw Czarnowski public: 1116107077deSPrzemyslaw Czarnowski /* 1117107077deSPrzemyslaw Czarnowski * Default Constructor 1118107077deSPrzemyslaw Czarnowski */ 111952cc112dSEd Tanous VirtualMedia(App& app) : 1120107077deSPrzemyslaw Czarnowski Node(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/", 1121107077deSPrzemyslaw Czarnowski std::string(), std::string()) 1122107077deSPrzemyslaw Czarnowski { 1123107077deSPrzemyslaw Czarnowski entityPrivileges = { 1124107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 1125107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 1126107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 1127107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 1128107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 1129107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 1130107077deSPrzemyslaw Czarnowski } 1131107077deSPrzemyslaw Czarnowski 1132107077deSPrzemyslaw Czarnowski private: 1133107077deSPrzemyslaw Czarnowski /** 1134107077deSPrzemyslaw Czarnowski * Functions triggers appropriate requests on DBus 1135107077deSPrzemyslaw Czarnowski */ 1136*8d1b46d7Szhanghch05 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1137*8d1b46d7Szhanghch05 const crow::Request&, 1138107077deSPrzemyslaw Czarnowski const std::vector<std::string>& params) override 1139107077deSPrzemyslaw Czarnowski { 1140107077deSPrzemyslaw Czarnowski // Check if there is required param, truly entering this shall be 1141107077deSPrzemyslaw Czarnowski // impossible 1142107077deSPrzemyslaw Czarnowski if (params.size() != 2) 1143107077deSPrzemyslaw Czarnowski { 1144*8d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 1145107077deSPrzemyslaw Czarnowski return; 1146107077deSPrzemyslaw Czarnowski } 1147107077deSPrzemyslaw Czarnowski const std::string& name = params[0]; 1148107077deSPrzemyslaw Czarnowski const std::string& resName = params[1]; 1149107077deSPrzemyslaw Czarnowski 1150107077deSPrzemyslaw Czarnowski if (name != "bmc") 1151107077deSPrzemyslaw Czarnowski { 1152107077deSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName); 1153107077deSPrzemyslaw Czarnowski 1154107077deSPrzemyslaw Czarnowski return; 1155107077deSPrzemyslaw Czarnowski } 1156107077deSPrzemyslaw Czarnowski 1157107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1158107077deSPrzemyslaw Czarnowski [asyncResp, name, resName](const boost::system::error_code ec, 1159107077deSPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 1160107077deSPrzemyslaw Czarnowski if (ec) 1161107077deSPrzemyslaw Czarnowski { 1162107077deSPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 1163107077deSPrzemyslaw Czarnowski << ec; 1164107077deSPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1165107077deSPrzemyslaw Czarnowski 1166107077deSPrzemyslaw Czarnowski return; 1167107077deSPrzemyslaw Czarnowski } 1168107077deSPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 1169107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 1170107077deSPrzemyslaw Czarnowski 1171107077deSPrzemyslaw Czarnowski getVmData(asyncResp, service, name, resName); 1172107077deSPrzemyslaw Czarnowski }, 1173107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 1174107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 1175107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 1176107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 1177107077deSPrzemyslaw Czarnowski } 1178107077deSPrzemyslaw Czarnowski }; 1179107077deSPrzemyslaw Czarnowski 1180107077deSPrzemyslaw Czarnowski } // namespace redfish 1181