1*40e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 2*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation 4107077deSPrzemyslaw Czarnowski #pragma once 5107077deSPrzemyslaw Czarnowski 63ccb3adbSEd Tanous #include "account_service.hpp" 73ccb3adbSEd Tanous #include "app.hpp" 879fdf63eSPrzemyslaw Czarnowski #include "async_resp.hpp" 911e8f60dSEd Tanous #include "credential_pipe.hpp" 102b73119cSGeorge Liu #include "dbus_utility.hpp" 11739b87efSEd Tanous #include "generated/enums/virtual_media.hpp" 123ccb3adbSEd Tanous #include "query.hpp" 133ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 143ccb3adbSEd Tanous #include "utils/json_utils.hpp" 153ccb3adbSEd Tanous 16ef4c65b7SEd Tanous #include <boost/url/format.hpp> 179e319cf0SAnna Platash #include <boost/url/url_view.hpp> 184a7fbefdSEd Tanous #include <boost/url/url_view_base.hpp> 19107077deSPrzemyslaw Czarnowski 202b73119cSGeorge Liu #include <array> 213544d2a7SEd Tanous #include <ranges> 222b73119cSGeorge Liu #include <string_view> 232b73119cSGeorge Liu 24107077deSPrzemyslaw Czarnowski namespace redfish 25107077deSPrzemyslaw Czarnowski { 26365a73f4SEd Tanous 27365a73f4SEd Tanous enum class VmMode 28365a73f4SEd Tanous { 29365a73f4SEd Tanous Invalid, 30365a73f4SEd Tanous Legacy, 31365a73f4SEd Tanous Proxy 32365a73f4SEd Tanous }; 33365a73f4SEd Tanous 34bd79bce8SPatrick Williams inline VmMode parseObjectPathAndGetMode( 35bd79bce8SPatrick Williams const sdbusplus::message::object_path& itemPath, const std::string& resName) 36365a73f4SEd Tanous { 37365a73f4SEd Tanous std::string thisPath = itemPath.filename(); 3862598e31SEd Tanous BMCWEB_LOG_DEBUG("Filename: {}, ThisPath: {}", itemPath.str, thisPath); 39365a73f4SEd Tanous 40365a73f4SEd Tanous if (thisPath.empty()) 41365a73f4SEd Tanous { 42365a73f4SEd Tanous return VmMode::Invalid; 43365a73f4SEd Tanous } 44365a73f4SEd Tanous 45365a73f4SEd Tanous if (thisPath != resName) 46365a73f4SEd Tanous { 47365a73f4SEd Tanous return VmMode::Invalid; 48365a73f4SEd Tanous } 49365a73f4SEd Tanous 50365a73f4SEd Tanous auto mode = itemPath.parent_path(); 51365a73f4SEd Tanous auto type = mode.parent_path(); 52365a73f4SEd Tanous 53365a73f4SEd Tanous if (mode.filename().empty() || type.filename().empty()) 54365a73f4SEd Tanous { 55365a73f4SEd Tanous return VmMode::Invalid; 56365a73f4SEd Tanous } 57365a73f4SEd Tanous 58365a73f4SEd Tanous if (type.filename() != "VirtualMedia") 59365a73f4SEd Tanous { 60365a73f4SEd Tanous return VmMode::Invalid; 61365a73f4SEd Tanous } 62365a73f4SEd Tanous std::string modeStr = mode.filename(); 63365a73f4SEd Tanous if (modeStr == "Legacy") 64365a73f4SEd Tanous { 65365a73f4SEd Tanous return VmMode::Legacy; 66365a73f4SEd Tanous } 67365a73f4SEd Tanous if (modeStr == "Proxy") 68365a73f4SEd Tanous { 69365a73f4SEd Tanous return VmMode::Proxy; 70365a73f4SEd Tanous } 71365a73f4SEd Tanous return VmMode::Invalid; 72365a73f4SEd Tanous } 73365a73f4SEd Tanous 7479fdf63eSPrzemyslaw Czarnowski using CheckItemHandler = 7579fdf63eSPrzemyslaw Czarnowski std::function<void(const std::string& service, const std::string& resName, 7679fdf63eSPrzemyslaw Czarnowski const std::shared_ptr<bmcweb::AsyncResp>&, 7770cbdf53SGeorge Liu const std::pair<sdbusplus::message::object_path, 7880f79a40SMichael Shen dbus::utility::DBusInterfacesMap>&)>; 7979fdf63eSPrzemyslaw Czarnowski 80ac106bf6SEd Tanous inline void 81ac106bf6SEd Tanous findAndParseObject(const std::string& service, const std::string& resName, 82ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8379fdf63eSPrzemyslaw Czarnowski CheckItemHandler&& handler) 8479fdf63eSPrzemyslaw Czarnowski { 855eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/VirtualMedia"); 865eb468daSGeorge Liu dbus::utility::getManagedObjects( 875eb468daSGeorge Liu service, path, 888cb2c024SEd Tanous [service, resName, asyncResp, handler = std::move(handler)]( 898cb2c024SEd Tanous const boost::system::error_code& ec, 9070cbdf53SGeorge Liu const dbus::utility::ManagedObjectType& subtree) { 9179fdf63eSPrzemyslaw Czarnowski if (ec) 9279fdf63eSPrzemyslaw Czarnowski { 9362598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 9479fdf63eSPrzemyslaw Czarnowski 9579fdf63eSPrzemyslaw Czarnowski return; 9679fdf63eSPrzemyslaw Czarnowski } 9779fdf63eSPrzemyslaw Czarnowski 9870cbdf53SGeorge Liu for (const auto& item : subtree) 9979fdf63eSPrzemyslaw Czarnowski { 10079fdf63eSPrzemyslaw Czarnowski VmMode mode = parseObjectPathAndGetMode(item.first, resName); 10179fdf63eSPrzemyslaw Czarnowski if (mode != VmMode::Invalid) 10279fdf63eSPrzemyslaw Czarnowski { 103ac106bf6SEd Tanous handler(service, resName, asyncResp, item); 10479fdf63eSPrzemyslaw Czarnowski return; 10579fdf63eSPrzemyslaw Czarnowski } 10679fdf63eSPrzemyslaw Czarnowski } 10779fdf63eSPrzemyslaw Czarnowski 10862598e31SEd Tanous BMCWEB_LOG_DEBUG("Parent item not found"); 109ac106bf6SEd Tanous asyncResp->res.result(boost::beast::http::status::not_found); 1105eb468daSGeorge Liu }); 11179fdf63eSPrzemyslaw Czarnowski } 11279fdf63eSPrzemyslaw Czarnowski 1139e319cf0SAnna Platash /** 1149e319cf0SAnna Platash * @brief Function extracts transfer protocol name from URI. 1159e319cf0SAnna Platash */ 11667df073bSEd Tanous inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri) 11767df073bSEd Tanous { 1186fd29553SEd Tanous boost::system::result<boost::urls::url_view> url = 119079360aeSEd Tanous boost::urls::parse_uri(imageUri); 12067df073bSEd Tanous if (!url) 12167df073bSEd Tanous { 12267df073bSEd Tanous return "None"; 12367df073bSEd Tanous } 124079360aeSEd Tanous std::string_view scheme = url->scheme(); 12567df073bSEd Tanous if (scheme == "smb") 12667df073bSEd Tanous { 12767df073bSEd Tanous return "CIFS"; 12867df073bSEd Tanous } 12967df073bSEd Tanous if (scheme == "https") 13067df073bSEd Tanous { 13167df073bSEd Tanous return "HTTPS"; 13267df073bSEd Tanous } 13367df073bSEd Tanous 13467df073bSEd Tanous return "None"; 13567df073bSEd Tanous } 136107077deSPrzemyslaw Czarnowski 137107077deSPrzemyslaw Czarnowski /** 138107077deSPrzemyslaw Czarnowski * @brief Read all known properties from VM object interfaces 139107077deSPrzemyslaw Czarnowski */ 14022db1728SEd Tanous inline void 14180f79a40SMichael Shen vmParseInterfaceObject(const dbus::utility::DBusInterfacesMap& interfaces, 142ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 143107077deSPrzemyslaw Czarnowski { 1448a592810SEd Tanous for (const auto& [interface, values] : interfaces) 145107077deSPrzemyslaw Czarnowski { 146711ac7a9SEd Tanous if (interface == "xyz.openbmc_project.VirtualMedia.MountPoint") 147107077deSPrzemyslaw Czarnowski { 148711ac7a9SEd Tanous for (const auto& [property, value] : values) 149107077deSPrzemyslaw Czarnowski { 150711ac7a9SEd Tanous if (property == "EndpointId") 151107077deSPrzemyslaw Czarnowski { 152107077deSPrzemyslaw Czarnowski const std::string* endpointIdValue = 153711ac7a9SEd Tanous std::get_if<std::string>(&value); 154711ac7a9SEd Tanous if (endpointIdValue == nullptr) 155107077deSPrzemyslaw Czarnowski { 156711ac7a9SEd Tanous continue; 157711ac7a9SEd Tanous } 158107077deSPrzemyslaw Czarnowski if (!endpointIdValue->empty()) 159107077deSPrzemyslaw Czarnowski { 160107077deSPrzemyslaw Czarnowski // Proxy mode 161ac106bf6SEd Tanous asyncResp->res 162711ac7a9SEd Tanous .jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] = 163d04ba325SPrzemyslaw Czarnowski *endpointIdValue; 164ac106bf6SEd Tanous asyncResp->res.jsonValue["TransferProtocolType"] = 165ac106bf6SEd Tanous "OEM"; 166107077deSPrzemyslaw Czarnowski } 167107077deSPrzemyslaw Czarnowski } 168711ac7a9SEd Tanous if (property == "ImageURL") 169107077deSPrzemyslaw Czarnowski { 170107077deSPrzemyslaw Czarnowski const std::string* imageUrlValue = 171711ac7a9SEd Tanous std::get_if<std::string>(&value); 17226f6976fSEd Tanous if (imageUrlValue != nullptr && !imageUrlValue->empty()) 173107077deSPrzemyslaw Czarnowski { 174da4784d8SPrzemyslaw Czarnowski std::filesystem::path filePath = *imageUrlValue; 175da4784d8SPrzemyslaw Czarnowski if (!filePath.has_filename()) 176da4784d8SPrzemyslaw Czarnowski { 1779e319cf0SAnna Platash // this will handle https share, which not 1789e319cf0SAnna Platash // necessarily has to have filename given. 179ac106bf6SEd Tanous asyncResp->res.jsonValue["ImageName"] = ""; 180da4784d8SPrzemyslaw Czarnowski } 181da4784d8SPrzemyslaw Czarnowski else 182da4784d8SPrzemyslaw Czarnowski { 183ac106bf6SEd Tanous asyncResp->res.jsonValue["ImageName"] = 1849e319cf0SAnna Platash filePath.filename(); 185da4784d8SPrzemyslaw Czarnowski } 186da4784d8SPrzemyslaw Czarnowski 187ac106bf6SEd Tanous asyncResp->res.jsonValue["Image"] = *imageUrlValue; 188ac106bf6SEd Tanous asyncResp->res.jsonValue["TransferProtocolType"] = 1899e319cf0SAnna Platash getTransferProtocolTypeFromUri(*imageUrlValue); 1909e319cf0SAnna Platash 191ac106bf6SEd Tanous asyncResp->res.jsonValue["ConnectedVia"] = 192739b87efSEd Tanous virtual_media::ConnectedVia::URI; 193107077deSPrzemyslaw Czarnowski } 194107077deSPrzemyslaw Czarnowski } 195711ac7a9SEd Tanous if (property == "WriteProtected") 1969e319cf0SAnna Platash { 197711ac7a9SEd Tanous const bool* writeProtectedValue = std::get_if<bool>(&value); 198e662eae8SEd Tanous if (writeProtectedValue != nullptr) 1999e319cf0SAnna Platash { 200ac106bf6SEd Tanous asyncResp->res.jsonValue["WriteProtected"] = 2019e319cf0SAnna Platash *writeProtectedValue; 2029e319cf0SAnna Platash } 2039e319cf0SAnna Platash } 2049e319cf0SAnna Platash } 205107077deSPrzemyslaw Czarnowski } 206711ac7a9SEd Tanous if (interface == "xyz.openbmc_project.VirtualMedia.Process") 207711ac7a9SEd Tanous { 208711ac7a9SEd Tanous for (const auto& [property, value] : values) 209711ac7a9SEd Tanous { 210711ac7a9SEd Tanous if (property == "Active") 211711ac7a9SEd Tanous { 212711ac7a9SEd Tanous const bool* activeValue = std::get_if<bool>(&value); 213e662eae8SEd Tanous if (activeValue == nullptr) 214711ac7a9SEd Tanous { 21562598e31SEd Tanous BMCWEB_LOG_DEBUG("Value Active not found"); 216711ac7a9SEd Tanous return; 217711ac7a9SEd Tanous } 218ac106bf6SEd Tanous asyncResp->res.jsonValue["Inserted"] = *activeValue; 219711ac7a9SEd Tanous 220e05aec50SEd Tanous if (*activeValue) 221711ac7a9SEd Tanous { 222ac106bf6SEd Tanous asyncResp->res.jsonValue["ConnectedVia"] = 223739b87efSEd Tanous virtual_media::ConnectedVia::Applet; 224711ac7a9SEd Tanous } 225711ac7a9SEd Tanous } 226711ac7a9SEd Tanous } 227711ac7a9SEd Tanous } 228107077deSPrzemyslaw Czarnowski } 229107077deSPrzemyslaw Czarnowski } 230107077deSPrzemyslaw Czarnowski 231107077deSPrzemyslaw Czarnowski /** 232107077deSPrzemyslaw Czarnowski * @brief Fill template for Virtual Media Item. 233107077deSPrzemyslaw Czarnowski */ 23422db1728SEd Tanous inline nlohmann::json vmItemTemplate(const std::string& name, 235107077deSPrzemyslaw Czarnowski const std::string& resName) 236107077deSPrzemyslaw Czarnowski { 237107077deSPrzemyslaw Czarnowski nlohmann::json item; 238ef4c65b7SEd Tanous item["@odata.id"] = boost::urls::format( 239ef4c65b7SEd Tanous "/redfish/v1/Managers/{}/VirtualMedia/{}", name, resName); 24022db1728SEd Tanous 241d04ba325SPrzemyslaw Czarnowski item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia"; 242107077deSPrzemyslaw Czarnowski item["Name"] = "Virtual Removable Media"; 243107077deSPrzemyslaw Czarnowski item["Id"] = resName; 244107077deSPrzemyslaw Czarnowski item["WriteProtected"] = true; 245739b87efSEd Tanous item["ConnectedVia"] = virtual_media::ConnectedVia::NotConnected; 246613dabeaSEd Tanous item["MediaTypes"] = nlohmann::json::array_t({"CD", "USBStick"}); 247539d8c6bSEd Tanous item["TransferMethod"] = virtual_media::TransferMethod::Stream; 248d04ba325SPrzemyslaw Czarnowski item["Oem"]["OpenBMC"]["@odata.type"] = 249f958ed9cSEd Tanous "#OpenBMCVirtualMedia.v1_0_0.VirtualMedia"; 25015b89725SV-Sanjana item["Oem"]["OpenBMC"]["@odata.id"] = boost::urls::format( 25115b89725SV-Sanjana "/redfish/v1/Managers/{}/VirtualMedia/{}#/Oem/OpenBMC", name, resName); 252107077deSPrzemyslaw Czarnowski 253107077deSPrzemyslaw Czarnowski return item; 254107077deSPrzemyslaw Czarnowski } 255107077deSPrzemyslaw Czarnowski 256107077deSPrzemyslaw Czarnowski /** 257107077deSPrzemyslaw Czarnowski * @brief Fills collection data 258107077deSPrzemyslaw Czarnowski */ 259ac106bf6SEd Tanous inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 260107077deSPrzemyslaw Czarnowski const std::string& service, 261107077deSPrzemyslaw Czarnowski const std::string& name) 262107077deSPrzemyslaw Czarnowski { 26362598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available Virtual Media resources."); 2645eb468daSGeorge Liu sdbusplus::message::object_path objPath( 2655eb468daSGeorge Liu "/xyz/openbmc_project/VirtualMedia"); 2665eb468daSGeorge Liu dbus::utility::getManagedObjects( 2675eb468daSGeorge Liu service, objPath, 268ac106bf6SEd Tanous [name, asyncResp{std::move(asyncResp)}]( 2695e7e2dc5SEd Tanous const boost::system::error_code& ec, 27002cad96eSEd Tanous const dbus::utility::ManagedObjectType& subtree) { 271107077deSPrzemyslaw Czarnowski if (ec) 272107077deSPrzemyslaw Czarnowski { 27362598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 274107077deSPrzemyslaw Czarnowski return; 275107077deSPrzemyslaw Czarnowski } 276ac106bf6SEd Tanous nlohmann::json& members = asyncResp->res.jsonValue["Members"]; 277107077deSPrzemyslaw Czarnowski members = nlohmann::json::array(); 278107077deSPrzemyslaw Czarnowski 279107077deSPrzemyslaw Czarnowski for (const auto& object : subtree) 280107077deSPrzemyslaw Czarnowski { 281107077deSPrzemyslaw Czarnowski nlohmann::json item; 2822dfd18efSEd Tanous std::string path = object.first.filename(); 2832dfd18efSEd Tanous if (path.empty()) 284107077deSPrzemyslaw Czarnowski { 285107077deSPrzemyslaw Czarnowski continue; 286107077deSPrzemyslaw Czarnowski } 287107077deSPrzemyslaw Czarnowski 288ef4c65b7SEd Tanous item["@odata.id"] = boost::urls::format( 289ef4c65b7SEd Tanous "/redfish/v1/Managers/{}/VirtualMedia/{}", name, path); 290107077deSPrzemyslaw Czarnowski members.emplace_back(std::move(item)); 291107077deSPrzemyslaw Czarnowski } 292ac106bf6SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = members.size(); 2935eb468daSGeorge Liu }); 294107077deSPrzemyslaw Czarnowski } 295107077deSPrzemyslaw Czarnowski 29670cbdf53SGeorge Liu inline void 29770cbdf53SGeorge Liu afterGetVmData(const std::string& name, const std::string& /*service*/, 29879fdf63eSPrzemyslaw Czarnowski const std::string& resName, 29979fdf63eSPrzemyslaw Czarnowski const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 30070cbdf53SGeorge Liu const std::pair<sdbusplus::message::object_path, 30180f79a40SMichael Shen dbus::utility::DBusInterfacesMap>& item) 30279fdf63eSPrzemyslaw Czarnowski { 30379fdf63eSPrzemyslaw Czarnowski VmMode mode = parseObjectPathAndGetMode(item.first, resName); 30479fdf63eSPrzemyslaw Czarnowski if (mode == VmMode::Invalid) 30579fdf63eSPrzemyslaw Czarnowski { 30679fdf63eSPrzemyslaw Czarnowski return; 30779fdf63eSPrzemyslaw Czarnowski } 30879fdf63eSPrzemyslaw Czarnowski 30979fdf63eSPrzemyslaw Czarnowski asyncResp->res.jsonValue = vmItemTemplate(name, resName); 31079fdf63eSPrzemyslaw Czarnowski 31179fdf63eSPrzemyslaw Czarnowski // Check if dbus path is Legacy type 31279fdf63eSPrzemyslaw Czarnowski if (mode == VmMode::Legacy) 31379fdf63eSPrzemyslaw Czarnowski { 314ef4c65b7SEd Tanous asyncResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"] 315ef4c65b7SEd Tanous ["target"] = boost::urls::format( 316ef4c65b7SEd Tanous "/redfish/v1/Managers/{}/VirtualMedia/{}/Actions/VirtualMedia.InsertMedia", 317ef4c65b7SEd Tanous name, resName); 31879fdf63eSPrzemyslaw Czarnowski } 31979fdf63eSPrzemyslaw Czarnowski 32079fdf63eSPrzemyslaw Czarnowski vmParseInterfaceObject(item.second, asyncResp); 32179fdf63eSPrzemyslaw Czarnowski 322ef4c65b7SEd Tanous asyncResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"] 323ef4c65b7SEd Tanous ["target"] = boost::urls::format( 324ef4c65b7SEd Tanous "/redfish/v1/Managers/{}/VirtualMedia/{}/Actions/VirtualMedia.EjectMedia", 325ef4c65b7SEd Tanous name, resName); 32679fdf63eSPrzemyslaw Czarnowski } 32779fdf63eSPrzemyslaw Czarnowski 328107077deSPrzemyslaw Czarnowski /** 329107077deSPrzemyslaw Czarnowski * @brief Fills data for specific resource 330107077deSPrzemyslaw Czarnowski */ 331ac106bf6SEd Tanous inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 332107077deSPrzemyslaw Czarnowski const std::string& service, const std::string& name, 333107077deSPrzemyslaw Czarnowski const std::string& resName) 334107077deSPrzemyslaw Czarnowski { 33562598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Virtual Media resource data."); 336107077deSPrzemyslaw Czarnowski 337ac106bf6SEd Tanous findAndParseObject(service, resName, asyncResp, 33870cbdf53SGeorge Liu std::bind_front(afterGetVmData, name)); 339107077deSPrzemyslaw Czarnowski } 340107077deSPrzemyslaw Czarnowski 341e13c2760SPrzemyslaw Czarnowski /** 342c6f4e017SAgata Olender * @brief Transfer protocols supported for InsertMedia action. 343c6f4e017SAgata Olender * 344c6f4e017SAgata Olender */ 345c6f4e017SAgata Olender enum class TransferProtocol 346c6f4e017SAgata Olender { 347c6f4e017SAgata Olender https, 348c6f4e017SAgata Olender smb, 349c6f4e017SAgata Olender invalid 350c6f4e017SAgata Olender }; 351c6f4e017SAgata Olender 352c6f4e017SAgata Olender /** 353c6f4e017SAgata Olender * @brief Function extracts transfer protocol type from URI. 354c6f4e017SAgata Olender * 355c6f4e017SAgata Olender */ 35667df073bSEd Tanous inline std::optional<TransferProtocol> 3574a7fbefdSEd Tanous getTransferProtocolFromUri(const boost::urls::url_view_base& imageUri) 35867df073bSEd Tanous { 359079360aeSEd Tanous std::string_view scheme = imageUri.scheme(); 36067df073bSEd Tanous if (scheme == "smb") 36167df073bSEd Tanous { 36267df073bSEd Tanous return TransferProtocol::smb; 36367df073bSEd Tanous } 36467df073bSEd Tanous if (scheme == "https") 36567df073bSEd Tanous { 36667df073bSEd Tanous return TransferProtocol::https; 36767df073bSEd Tanous } 36867df073bSEd Tanous if (!scheme.empty()) 36967df073bSEd Tanous { 37067df073bSEd Tanous return TransferProtocol::invalid; 37167df073bSEd Tanous } 37267df073bSEd Tanous 37367df073bSEd Tanous return {}; 37467df073bSEd Tanous } 375c6f4e017SAgata Olender 376c6f4e017SAgata Olender /** 377c6f4e017SAgata Olender * @brief Function convert transfer protocol from string param. 378c6f4e017SAgata Olender * 379c6f4e017SAgata Olender */ 38022db1728SEd Tanous inline std::optional<TransferProtocol> getTransferProtocolFromParam( 381c6f4e017SAgata Olender const std::optional<std::string>& transferProtocolType) 382c6f4e017SAgata Olender { 383e01d0c36SEd Tanous if (!transferProtocolType) 384c6f4e017SAgata Olender { 385c6f4e017SAgata Olender return {}; 386c6f4e017SAgata Olender } 387c6f4e017SAgata Olender 388c6f4e017SAgata Olender if (*transferProtocolType == "CIFS") 389c6f4e017SAgata Olender { 390c6f4e017SAgata Olender return TransferProtocol::smb; 391c6f4e017SAgata Olender } 392c6f4e017SAgata Olender 393c6f4e017SAgata Olender if (*transferProtocolType == "HTTPS") 394c6f4e017SAgata Olender { 395c6f4e017SAgata Olender return TransferProtocol::https; 396c6f4e017SAgata Olender } 397c6f4e017SAgata Olender 398c6f4e017SAgata Olender return TransferProtocol::invalid; 399c6f4e017SAgata Olender } 400c6f4e017SAgata Olender 401c6f4e017SAgata Olender /** 402c6f4e017SAgata Olender * @brief Function extends URI with transfer protocol type. 403c6f4e017SAgata Olender * 404c6f4e017SAgata Olender */ 405bd79bce8SPatrick Williams inline std::string getUriWithTransferProtocol( 406bd79bce8SPatrick Williams const std::string& imageUri, const TransferProtocol& transferProtocol) 407c6f4e017SAgata Olender { 408c6f4e017SAgata Olender if (transferProtocol == TransferProtocol::smb) 409c6f4e017SAgata Olender { 410c6f4e017SAgata Olender return "smb://" + imageUri; 411c6f4e017SAgata Olender } 412c6f4e017SAgata Olender 413c6f4e017SAgata Olender if (transferProtocol == TransferProtocol::https) 414c6f4e017SAgata Olender { 415c6f4e017SAgata Olender return "https://" + imageUri; 416c6f4e017SAgata Olender } 417c6f4e017SAgata Olender 418c6f4e017SAgata Olender return imageUri; 419c6f4e017SAgata Olender } 420c6f4e017SAgata Olender 4211f2a40ceSPrzemyslaw Czarnowski struct InsertMediaActionParams 4221f2a40ceSPrzemyslaw Czarnowski { 423120fa86aSPrzemyslaw Czarnowski std::optional<std::string> imageUrl; 4241f2a40ceSPrzemyslaw Czarnowski std::optional<std::string> userName; 4251f2a40ceSPrzemyslaw Czarnowski std::optional<std::string> password; 4261f2a40ceSPrzemyslaw Czarnowski std::optional<std::string> transferMethod; 4271f2a40ceSPrzemyslaw Czarnowski std::optional<std::string> transferProtocolType; 4281f2a40ceSPrzemyslaw Czarnowski std::optional<bool> writeProtected = true; 4291f2a40ceSPrzemyslaw Czarnowski std::optional<bool> inserted; 4301f2a40ceSPrzemyslaw Czarnowski }; 4311f2a40ceSPrzemyslaw Czarnowski 432e13c2760SPrzemyslaw Czarnowski /** 433e13c2760SPrzemyslaw Czarnowski * @brief Function transceives data with dbus directly. 434e13c2760SPrzemyslaw Czarnowski * 435e13c2760SPrzemyslaw Czarnowski * All BMC state properties will be retrieved before sending reset request. 436e13c2760SPrzemyslaw Czarnowski */ 43722db1728SEd Tanous inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 438e13c2760SPrzemyslaw Czarnowski const std::string& service, const std::string& name, 43911e8f60dSEd Tanous const std::string& imageUrl, bool rw, 440988fb7b2SAdrian Ambrożewicz std::string&& userName, std::string&& password) 441e13c2760SPrzemyslaw Czarnowski { 44211e8f60dSEd Tanous int fd = -1; 44311e8f60dSEd Tanous std::shared_ptr<CredentialsPipe> secretPipe; 444988fb7b2SAdrian Ambrożewicz if (!userName.empty() || !password.empty()) 445988fb7b2SAdrian Ambrożewicz { 446988fb7b2SAdrian Ambrożewicz // Payload must contain data + NULL delimiters 44711e8f60dSEd Tanous constexpr const size_t secretLimit = 1024; 44811e8f60dSEd Tanous if (userName.size() + password.size() + 2 > secretLimit) 449988fb7b2SAdrian Ambrożewicz { 45062598e31SEd Tanous BMCWEB_LOG_ERROR("Credentials too long to handle"); 451988fb7b2SAdrian Ambrożewicz messages::unrecognizedRequestBody(asyncResp->res); 452988fb7b2SAdrian Ambrożewicz return; 453988fb7b2SAdrian Ambrożewicz } 454988fb7b2SAdrian Ambrożewicz 455988fb7b2SAdrian Ambrożewicz // Open pipe 45611e8f60dSEd Tanous secretPipe = std::make_shared<CredentialsPipe>( 45711e8f60dSEd Tanous crow::connections::systemBus->get_io_context()); 4583bfa3b29SEd Tanous fd = secretPipe->releaseFd(); 459988fb7b2SAdrian Ambrożewicz 460988fb7b2SAdrian Ambrożewicz // Pass secret over pipe 46181ce609eSEd Tanous secretPipe->asyncWrite( 46211e8f60dSEd Tanous std::move(userName), std::move(password), 463bd79bce8SPatrick Williams [asyncResp, 464bd79bce8SPatrick Williams secretPipe](const boost::system::error_code& ec, std::size_t) { 465988fb7b2SAdrian Ambrożewicz if (ec) 466988fb7b2SAdrian Ambrożewicz { 46762598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to pass secret: {}", ec); 468988fb7b2SAdrian Ambrożewicz messages::internalError(asyncResp->res); 469988fb7b2SAdrian Ambrożewicz } 470988fb7b2SAdrian Ambrożewicz }); 471988fb7b2SAdrian Ambrożewicz } 472988fb7b2SAdrian Ambrożewicz 473e3648032SEd Tanous std::variant<sdbusplus::message::unix_fd> unixFd( 47411e8f60dSEd Tanous std::in_place_type<sdbusplus::message::unix_fd>, fd); 47511e8f60dSEd Tanous 47611e8f60dSEd Tanous sdbusplus::message::object_path path( 47711e8f60dSEd Tanous "/xyz/openbmc_project/VirtualMedia/Legacy"); 47811e8f60dSEd Tanous path /= name; 479e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 480bd79bce8SPatrick Williams [asyncResp, 481bd79bce8SPatrick Williams secretPipe](const boost::system::error_code& ec, bool success) { 482e13c2760SPrzemyslaw Czarnowski if (ec) 483e13c2760SPrzemyslaw Czarnowski { 48462598e31SEd Tanous BMCWEB_LOG_ERROR("Bad D-Bus request error: {}", ec); 485e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 48611e8f60dSEd Tanous return; 487d6da5bebSAdrian Ambrożewicz } 48811e8f60dSEd Tanous if (!success) 489d6da5bebSAdrian Ambrożewicz { 49062598e31SEd Tanous BMCWEB_LOG_ERROR("Service responded with error"); 49111e8f60dSEd Tanous messages::internalError(asyncResp->res); 492e13c2760SPrzemyslaw Czarnowski } 493e13c2760SPrzemyslaw Czarnowski }, 49411e8f60dSEd Tanous service, path.str, "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", 49511e8f60dSEd Tanous imageUrl, rw, unixFd); 496e13c2760SPrzemyslaw Czarnowski } 497e13c2760SPrzemyslaw Czarnowski 498e13c2760SPrzemyslaw Czarnowski /** 499120fa86aSPrzemyslaw Czarnowski * @brief Function validate parameters of insert media request. 500120fa86aSPrzemyslaw Czarnowski * 501120fa86aSPrzemyslaw Czarnowski */ 502120fa86aSPrzemyslaw Czarnowski inline void validateParams(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 503120fa86aSPrzemyslaw Czarnowski const std::string& service, 504120fa86aSPrzemyslaw Czarnowski const std::string& resName, 505120fa86aSPrzemyslaw Czarnowski InsertMediaActionParams& actionParams) 506120fa86aSPrzemyslaw Czarnowski { 50762598e31SEd Tanous BMCWEB_LOG_DEBUG("Validation started"); 508120fa86aSPrzemyslaw Czarnowski // required param imageUrl must not be empty 509120fa86aSPrzemyslaw Czarnowski if (!actionParams.imageUrl) 510120fa86aSPrzemyslaw Czarnowski { 51162598e31SEd Tanous BMCWEB_LOG_ERROR("Request action parameter Image is empty."); 512120fa86aSPrzemyslaw Czarnowski 513120fa86aSPrzemyslaw Czarnowski messages::propertyValueFormatError(asyncResp->res, "<empty>", "Image"); 514120fa86aSPrzemyslaw Czarnowski 515120fa86aSPrzemyslaw Czarnowski return; 516120fa86aSPrzemyslaw Czarnowski } 517120fa86aSPrzemyslaw Czarnowski 518120fa86aSPrzemyslaw Czarnowski // optional param inserted must be true 519e01d0c36SEd Tanous if (actionParams.inserted && !*actionParams.inserted) 520120fa86aSPrzemyslaw Czarnowski { 52162598e31SEd Tanous BMCWEB_LOG_ERROR( 52262598e31SEd Tanous "Request action optional parameter Inserted must be true."); 523120fa86aSPrzemyslaw Czarnowski 524120fa86aSPrzemyslaw Czarnowski messages::actionParameterNotSupported(asyncResp->res, "Inserted", 525120fa86aSPrzemyslaw Czarnowski "InsertMedia"); 526120fa86aSPrzemyslaw Czarnowski 527120fa86aSPrzemyslaw Czarnowski return; 528120fa86aSPrzemyslaw Czarnowski } 529120fa86aSPrzemyslaw Czarnowski 530120fa86aSPrzemyslaw Czarnowski // optional param transferMethod must be stream 531e01d0c36SEd Tanous if (actionParams.transferMethod && 532120fa86aSPrzemyslaw Czarnowski (*actionParams.transferMethod != "Stream")) 533120fa86aSPrzemyslaw Czarnowski { 53462598e31SEd Tanous BMCWEB_LOG_ERROR("Request action optional parameter " 53562598e31SEd Tanous "TransferMethod must be Stream."); 536120fa86aSPrzemyslaw Czarnowski 537120fa86aSPrzemyslaw Czarnowski messages::actionParameterNotSupported(asyncResp->res, "TransferMethod", 538120fa86aSPrzemyslaw Czarnowski "InsertMedia"); 539120fa86aSPrzemyslaw Czarnowski 540120fa86aSPrzemyslaw Czarnowski return; 541120fa86aSPrzemyslaw Czarnowski } 5426fd29553SEd Tanous boost::system::result<boost::urls::url_view> url = 543120fa86aSPrzemyslaw Czarnowski boost::urls::parse_uri(*actionParams.imageUrl); 544120fa86aSPrzemyslaw Czarnowski if (!url) 545120fa86aSPrzemyslaw Czarnowski { 546120fa86aSPrzemyslaw Czarnowski messages::actionParameterValueFormatError( 547120fa86aSPrzemyslaw Czarnowski asyncResp->res, *actionParams.imageUrl, "Image", "InsertMedia"); 548120fa86aSPrzemyslaw Czarnowski return; 549120fa86aSPrzemyslaw Czarnowski } 550120fa86aSPrzemyslaw Czarnowski std::optional<TransferProtocol> uriTransferProtocolType = 551120fa86aSPrzemyslaw Czarnowski getTransferProtocolFromUri(*url); 552120fa86aSPrzemyslaw Czarnowski 553120fa86aSPrzemyslaw Czarnowski std::optional<TransferProtocol> paramTransferProtocolType = 554120fa86aSPrzemyslaw Czarnowski getTransferProtocolFromParam(actionParams.transferProtocolType); 555120fa86aSPrzemyslaw Czarnowski 556120fa86aSPrzemyslaw Czarnowski // ImageUrl does not contain valid protocol type 557e01d0c36SEd Tanous if (uriTransferProtocolType && 558e01d0c36SEd Tanous *uriTransferProtocolType == TransferProtocol::invalid) 559120fa86aSPrzemyslaw Czarnowski { 56062598e31SEd Tanous BMCWEB_LOG_ERROR("Request action parameter ImageUrl must " 561120fa86aSPrzemyslaw Czarnowski "contain specified protocol type from list: " 56262598e31SEd Tanous "(smb, https)."); 563120fa86aSPrzemyslaw Czarnowski 564120fa86aSPrzemyslaw Czarnowski messages::resourceAtUriInUnknownFormat(asyncResp->res, *url); 565120fa86aSPrzemyslaw Czarnowski 566120fa86aSPrzemyslaw Czarnowski return; 567120fa86aSPrzemyslaw Czarnowski } 568120fa86aSPrzemyslaw Czarnowski 569120fa86aSPrzemyslaw Czarnowski // transferProtocolType should contain value from list 570e01d0c36SEd Tanous if (paramTransferProtocolType && 571e01d0c36SEd Tanous *paramTransferProtocolType == TransferProtocol::invalid) 572120fa86aSPrzemyslaw Czarnowski { 57362598e31SEd Tanous BMCWEB_LOG_ERROR("Request action parameter TransferProtocolType " 574120fa86aSPrzemyslaw Czarnowski "must be provided with value from list: " 57562598e31SEd Tanous "(CIFS, HTTPS)."); 576120fa86aSPrzemyslaw Czarnowski 577e01d0c36SEd Tanous messages::propertyValueNotInList( 578e01d0c36SEd Tanous asyncResp->res, actionParams.transferProtocolType.value_or(""), 579120fa86aSPrzemyslaw Czarnowski "TransferProtocolType"); 580120fa86aSPrzemyslaw Czarnowski return; 581120fa86aSPrzemyslaw Czarnowski } 582120fa86aSPrzemyslaw Czarnowski 583120fa86aSPrzemyslaw Czarnowski // valid transfer protocol not provided either with URI nor param 584e01d0c36SEd Tanous if (!uriTransferProtocolType && !paramTransferProtocolType) 585120fa86aSPrzemyslaw Czarnowski { 58662598e31SEd Tanous BMCWEB_LOG_ERROR("Request action parameter ImageUrl must " 587120fa86aSPrzemyslaw Czarnowski "contain specified protocol type or param " 58862598e31SEd Tanous "TransferProtocolType must be provided."); 589120fa86aSPrzemyslaw Czarnowski 590120fa86aSPrzemyslaw Czarnowski messages::resourceAtUriInUnknownFormat(asyncResp->res, *url); 591120fa86aSPrzemyslaw Czarnowski 592120fa86aSPrzemyslaw Czarnowski return; 593120fa86aSPrzemyslaw Czarnowski } 594120fa86aSPrzemyslaw Czarnowski 595120fa86aSPrzemyslaw Czarnowski // valid transfer protocol provided both with URI and param 596e01d0c36SEd Tanous if (paramTransferProtocolType && uriTransferProtocolType) 597120fa86aSPrzemyslaw Czarnowski { 598120fa86aSPrzemyslaw Czarnowski // check if protocol is the same for URI and param 599120fa86aSPrzemyslaw Czarnowski if (*paramTransferProtocolType != *uriTransferProtocolType) 600120fa86aSPrzemyslaw Czarnowski { 60162598e31SEd Tanous BMCWEB_LOG_ERROR("Request action parameter " 602120fa86aSPrzemyslaw Czarnowski "TransferProtocolType must contain the " 603120fa86aSPrzemyslaw Czarnowski "same protocol type as protocol type " 60462598e31SEd Tanous "provided with param imageUrl."); 605120fa86aSPrzemyslaw Czarnowski 606120fa86aSPrzemyslaw Czarnowski messages::actionParameterValueTypeError( 607e01d0c36SEd Tanous asyncResp->res, actionParams.transferProtocolType.value_or(""), 608120fa86aSPrzemyslaw Czarnowski "TransferProtocolType", "InsertMedia"); 609120fa86aSPrzemyslaw Czarnowski 610120fa86aSPrzemyslaw Czarnowski return; 611120fa86aSPrzemyslaw Czarnowski } 612120fa86aSPrzemyslaw Czarnowski } 613120fa86aSPrzemyslaw Czarnowski 614120fa86aSPrzemyslaw Czarnowski // validation passed, add protocol to URI if needed 6157ead48e6SBoleslaw Ogonczyk Makowski if (!uriTransferProtocolType && paramTransferProtocolType) 616120fa86aSPrzemyslaw Czarnowski { 617120fa86aSPrzemyslaw Czarnowski actionParams.imageUrl = getUriWithTransferProtocol( 618120fa86aSPrzemyslaw Czarnowski *actionParams.imageUrl, *paramTransferProtocolType); 619120fa86aSPrzemyslaw Czarnowski } 620120fa86aSPrzemyslaw Czarnowski 621452bd8d8SJayaprakash Mutyala if (!actionParams.userName) 622452bd8d8SJayaprakash Mutyala { 623452bd8d8SJayaprakash Mutyala actionParams.userName = ""; 624452bd8d8SJayaprakash Mutyala } 625452bd8d8SJayaprakash Mutyala 626452bd8d8SJayaprakash Mutyala if (!actionParams.password) 627452bd8d8SJayaprakash Mutyala { 628452bd8d8SJayaprakash Mutyala actionParams.password = ""; 629452bd8d8SJayaprakash Mutyala } 630452bd8d8SJayaprakash Mutyala 631120fa86aSPrzemyslaw Czarnowski doMountVmLegacy(asyncResp, service, resName, *actionParams.imageUrl, 632e01d0c36SEd Tanous !(actionParams.writeProtected.value_or(false)), 633120fa86aSPrzemyslaw Czarnowski std::move(*actionParams.userName), 634120fa86aSPrzemyslaw Czarnowski std::move(*actionParams.password)); 635120fa86aSPrzemyslaw Czarnowski } 636120fa86aSPrzemyslaw Czarnowski 637120fa86aSPrzemyslaw Czarnowski /** 638e13c2760SPrzemyslaw Czarnowski * @brief Function transceives data with dbus directly. 639e13c2760SPrzemyslaw Czarnowski * 640e13c2760SPrzemyslaw Czarnowski * All BMC state properties will be retrieved before sending reset request. 641e13c2760SPrzemyslaw Czarnowski */ 64224e740a7SEd Tanous inline void doEjectAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 643e13c2760SPrzemyslaw Czarnowski const std::string& service, const std::string& name, 644e13c2760SPrzemyslaw Czarnowski bool legacy) 645e13c2760SPrzemyslaw Czarnowski { 646e13c2760SPrzemyslaw Czarnowski // Legacy mount requires parameter with image 647e13c2760SPrzemyslaw Czarnowski if (legacy) 648e13c2760SPrzemyslaw Czarnowski { 649e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 6505e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 651e13c2760SPrzemyslaw Czarnowski if (ec) 652e13c2760SPrzemyslaw Czarnowski { 65362598e31SEd Tanous BMCWEB_LOG_ERROR("Bad D-Bus request error: {}", ec); 654e13c2760SPrzemyslaw Czarnowski 655e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 656e13c2760SPrzemyslaw Czarnowski return; 657e13c2760SPrzemyslaw Czarnowski } 658e13c2760SPrzemyslaw Czarnowski }, 659e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, 660e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount"); 661e13c2760SPrzemyslaw Czarnowski } 662e13c2760SPrzemyslaw Czarnowski else // proxy 663e13c2760SPrzemyslaw Czarnowski { 664e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 6655e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 666e13c2760SPrzemyslaw Czarnowski if (ec) 667e13c2760SPrzemyslaw Czarnowski { 66862598e31SEd Tanous BMCWEB_LOG_ERROR("Bad D-Bus request error: {}", ec); 669e13c2760SPrzemyslaw Czarnowski 670e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 671e13c2760SPrzemyslaw Czarnowski return; 672e13c2760SPrzemyslaw Czarnowski } 673e13c2760SPrzemyslaw Czarnowski }, 674e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name, 675e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount"); 676e13c2760SPrzemyslaw Czarnowski } 677e13c2760SPrzemyslaw Czarnowski } 678e13c2760SPrzemyslaw Czarnowski 67996825bebSEd Tanous inline void handleManagersVirtualMediaActionInsertPost( 68096825bebSEd Tanous crow::App& app, const crow::Request& req, 68122db1728SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 68296825bebSEd Tanous const std::string& name, const std::string& resName) 68396825bebSEd Tanous { 6843ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 68545ca1b86SEd Tanous { 68645ca1b86SEd Tanous return; 68745ca1b86SEd Tanous } 68879fdf63eSPrzemyslaw Czarnowski 68979fdf63eSPrzemyslaw Czarnowski constexpr std::string_view action = "VirtualMedia.InsertMedia"; 69022db1728SEd Tanous if (name != "bmc") 691107077deSPrzemyslaw Czarnowski { 69279fdf63eSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, action, resName); 693107077deSPrzemyslaw Czarnowski 694107077deSPrzemyslaw Czarnowski return; 695107077deSPrzemyslaw Czarnowski } 69679fdf63eSPrzemyslaw Czarnowski InsertMediaActionParams actionParams; 69798be3e39SEd Tanous 698120fa86aSPrzemyslaw Czarnowski // Read obligatory parameters (url of image) 699afc474aeSMyung Bae if (!json_util::readJsonAction( // 700afc474aeSMyung Bae req, asyncResp->res, // 701afc474aeSMyung Bae "Image", actionParams.imageUrl, // 702afc474aeSMyung Bae "Inserted", actionParams.inserted, // 703afc474aeSMyung Bae "Password", actionParams.password, // 704afc474aeSMyung Bae "TransferMethod", actionParams.transferMethod, // 705afc474aeSMyung Bae "TransferProtocolType", actionParams.transferProtocolType, // 706afc474aeSMyung Bae "UserName", actionParams.userName, // 707afc474aeSMyung Bae "WriteProtected", actionParams.writeProtected // 708afc474aeSMyung Bae )) 70998be3e39SEd Tanous { 71098be3e39SEd Tanous return; 71198be3e39SEd Tanous } 712107077deSPrzemyslaw Czarnowski 7132b73119cSGeorge Liu dbus::utility::getDbusObject( 7142b73119cSGeorge Liu "/xyz/openbmc_project/VirtualMedia", {}, 71579fdf63eSPrzemyslaw Czarnowski [asyncResp, action, actionParams, 7162b73119cSGeorge Liu resName](const boost::system::error_code& ec, 717002d39b4SEd Tanous const dbus::utility::MapperGetObject& getObjectType) mutable { 71822db1728SEd Tanous if (ec) 71922db1728SEd Tanous { 72062598e31SEd Tanous BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", ec); 72179fdf63eSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, action, resName); 722107077deSPrzemyslaw Czarnowski 72322db1728SEd Tanous return; 72422db1728SEd Tanous } 72579fdf63eSPrzemyslaw Czarnowski 72622db1728SEd Tanous std::string service = getObjectType.begin()->first; 72762598e31SEd Tanous BMCWEB_LOG_DEBUG("GetObjectType: {}", service); 72822db1728SEd Tanous 7295eb468daSGeorge Liu sdbusplus::message::object_path path( 7305eb468daSGeorge Liu "/xyz/openbmc_project/VirtualMedia"); 7315eb468daSGeorge Liu dbus::utility::getManagedObjects( 7325eb468daSGeorge Liu service, path, 7335eb468daSGeorge Liu [service, resName, action, actionParams, asyncResp]( 7345eb468daSGeorge Liu const boost::system::error_code& ec2, 7355eb468daSGeorge Liu const dbus::utility::ManagedObjectType& subtree) mutable { 7368a592810SEd Tanous if (ec2) 73722db1728SEd Tanous { 73879fdf63eSPrzemyslaw Czarnowski // Not possible in proxy mode 73962598e31SEd Tanous BMCWEB_LOG_DEBUG("InsertMedia not " 74062598e31SEd Tanous "allowed in proxy mode"); 741bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, action, 742bd79bce8SPatrick Williams resName); 74322db1728SEd Tanous 74422db1728SEd Tanous return; 74522db1728SEd Tanous } 74622db1728SEd Tanous for (const auto& object : subtree) 74722db1728SEd Tanous { 748bd79bce8SPatrick Williams VmMode mode = 749bd79bce8SPatrick Williams parseObjectPathAndGetMode(object.first, resName); 7505880f0c5SBoleslaw Ogonczyk Makowski if (mode == VmMode::Legacy) 75122db1728SEd Tanous { 752bd79bce8SPatrick Williams validateParams(asyncResp, service, resName, 753bd79bce8SPatrick Williams actionParams); 75422db1728SEd Tanous 75522db1728SEd Tanous return; 75622db1728SEd Tanous } 75722db1728SEd Tanous } 75862598e31SEd Tanous BMCWEB_LOG_DEBUG("Parent item not found"); 759bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "VirtualMedia", 760bd79bce8SPatrick Williams resName); 7615eb468daSGeorge Liu }); 7622b73119cSGeorge Liu }); 76396825bebSEd Tanous } 76422db1728SEd Tanous 76596825bebSEd Tanous inline void handleManagersVirtualMediaActionEject( 76696825bebSEd Tanous crow::App& app, const crow::Request& req, 76722db1728SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 76896825bebSEd Tanous const std::string& managerName, const std::string& resName) 76996825bebSEd Tanous { 7703ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 77145ca1b86SEd Tanous { 77245ca1b86SEd Tanous return; 77345ca1b86SEd Tanous } 77479fdf63eSPrzemyslaw Czarnowski 77579fdf63eSPrzemyslaw Czarnowski constexpr std::string_view action = "VirtualMedia.EjectMedia"; 77696825bebSEd Tanous if (managerName != "bmc") 777107077deSPrzemyslaw Czarnowski { 77879fdf63eSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, action, resName); 77922db1728SEd Tanous 78022db1728SEd Tanous return; 78122db1728SEd Tanous } 78222db1728SEd Tanous 7832b73119cSGeorge Liu dbus::utility::getDbusObject( 7842b73119cSGeorge Liu "/xyz/openbmc_project/VirtualMedia", {}, 78579fdf63eSPrzemyslaw Czarnowski [asyncResp, action, 7862b73119cSGeorge Liu resName](const boost::system::error_code& ec2, 787b9d36b47SEd Tanous const dbus::utility::MapperGetObject& getObjectType) { 7888a592810SEd Tanous if (ec2) 78922db1728SEd Tanous { 790bd79bce8SPatrick Williams BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", 791bd79bce8SPatrick Williams ec2); 79222db1728SEd Tanous messages::internalError(asyncResp->res); 79322db1728SEd Tanous 79422db1728SEd Tanous return; 79522db1728SEd Tanous } 79622db1728SEd Tanous std::string service = getObjectType.begin()->first; 79762598e31SEd Tanous BMCWEB_LOG_DEBUG("GetObjectType: {}", service); 79822db1728SEd Tanous 7995eb468daSGeorge Liu sdbusplus::message::object_path path( 8005eb468daSGeorge Liu "/xyz/openbmc_project/VirtualMedia"); 8015eb468daSGeorge Liu dbus::utility::getManagedObjects( 8025eb468daSGeorge Liu service, path, 80379fdf63eSPrzemyslaw Czarnowski [resName, service, action, 80479fdf63eSPrzemyslaw Czarnowski asyncResp](const boost::system::error_code& ec, 80502cad96eSEd Tanous const dbus::utility::ManagedObjectType& subtree) { 80622db1728SEd Tanous if (ec) 80722db1728SEd Tanous { 80862598e31SEd Tanous BMCWEB_LOG_ERROR("ObjectMapper : No Service found"); 809bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, action, 810bd79bce8SPatrick Williams resName); 81122db1728SEd Tanous return; 81222db1728SEd Tanous } 81322db1728SEd Tanous 81422db1728SEd Tanous for (const auto& object : subtree) 81522db1728SEd Tanous { 816bd79bce8SPatrick Williams VmMode mode = 817bd79bce8SPatrick Williams parseObjectPathAndGetMode(object.first, resName); 818365a73f4SEd Tanous if (mode != VmMode::Invalid) 81922db1728SEd Tanous { 820365a73f4SEd Tanous doEjectAction(asyncResp, service, resName, 821365a73f4SEd Tanous mode == VmMode::Legacy); 8225880f0c5SBoleslaw Ogonczyk Makowski return; 82322db1728SEd Tanous } 82422db1728SEd Tanous } 82562598e31SEd Tanous BMCWEB_LOG_DEBUG("Parent item not found"); 826bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "VirtualMedia", 827bd79bce8SPatrick Williams resName); 8285eb468daSGeorge Liu }); 8292b73119cSGeorge Liu }); 83096825bebSEd Tanous } 83196825bebSEd Tanous 83296825bebSEd Tanous inline void handleManagersVirtualMediaCollectionGet( 83396825bebSEd Tanous crow::App& app, const crow::Request& req, 83422db1728SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 83596825bebSEd Tanous const std::string& name) 83696825bebSEd Tanous { 8373ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 83845ca1b86SEd Tanous { 83945ca1b86SEd Tanous return; 84045ca1b86SEd Tanous } 84122db1728SEd Tanous if (name != "bmc") 84222db1728SEd Tanous { 843002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "VirtualMedia", name); 844107077deSPrzemyslaw Czarnowski 845107077deSPrzemyslaw Czarnowski return; 846107077deSPrzemyslaw Czarnowski } 847107077deSPrzemyslaw Czarnowski 8488d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 849107077deSPrzemyslaw Czarnowski "#VirtualMediaCollection.VirtualMediaCollection"; 8508d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Virtual Media Services"; 851ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 852ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/VirtualMedia", name); 853107077deSPrzemyslaw Czarnowski 8542b73119cSGeorge Liu dbus::utility::getDbusObject( 8552b73119cSGeorge Liu "/xyz/openbmc_project/VirtualMedia", {}, 8562b73119cSGeorge Liu [asyncResp, name](const boost::system::error_code& ec, 857b9d36b47SEd Tanous const dbus::utility::MapperGetObject& getObjectType) { 858107077deSPrzemyslaw Czarnowski if (ec) 859107077deSPrzemyslaw Czarnowski { 86062598e31SEd Tanous BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", ec); 861107077deSPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 862107077deSPrzemyslaw Czarnowski 863107077deSPrzemyslaw Czarnowski return; 864107077deSPrzemyslaw Czarnowski } 865107077deSPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 86662598e31SEd Tanous BMCWEB_LOG_DEBUG("GetObjectType: {}", service); 867107077deSPrzemyslaw Czarnowski 868107077deSPrzemyslaw Czarnowski getVmResourceList(asyncResp, service, name); 8692b73119cSGeorge Liu }); 87096825bebSEd Tanous } 871107077deSPrzemyslaw Czarnowski 87296825bebSEd Tanous inline void 87396825bebSEd Tanous handleVirtualMediaGet(crow::App& app, const crow::Request& req, 87422db1728SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 87596825bebSEd Tanous const std::string& name, const std::string& resName) 87696825bebSEd Tanous { 8773ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 87845ca1b86SEd Tanous { 87945ca1b86SEd Tanous return; 88045ca1b86SEd Tanous } 881107077deSPrzemyslaw Czarnowski if (name != "bmc") 882107077deSPrzemyslaw Czarnowski { 883002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName); 884107077deSPrzemyslaw Czarnowski 885107077deSPrzemyslaw Czarnowski return; 886107077deSPrzemyslaw Czarnowski } 887107077deSPrzemyslaw Czarnowski 8882b73119cSGeorge Liu dbus::utility::getDbusObject( 8892b73119cSGeorge Liu "/xyz/openbmc_project/VirtualMedia", {}, 890002d39b4SEd Tanous [asyncResp, name, 8912b73119cSGeorge Liu resName](const boost::system::error_code& ec, 892b9d36b47SEd Tanous const dbus::utility::MapperGetObject& getObjectType) { 893107077deSPrzemyslaw Czarnowski if (ec) 894107077deSPrzemyslaw Czarnowski { 89562598e31SEd Tanous BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", ec); 896107077deSPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 897107077deSPrzemyslaw Czarnowski 898107077deSPrzemyslaw Czarnowski return; 899107077deSPrzemyslaw Czarnowski } 900107077deSPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 90162598e31SEd Tanous BMCWEB_LOG_DEBUG("GetObjectType: {}", service); 902107077deSPrzemyslaw Czarnowski 903107077deSPrzemyslaw Czarnowski getVmData(asyncResp, service, name, resName); 9042b73119cSGeorge Liu }); 90596825bebSEd Tanous } 90696825bebSEd Tanous 90796825bebSEd Tanous inline void requestNBDVirtualMediaRoutes(App& app) 90896825bebSEd Tanous { 90996825bebSEd Tanous BMCWEB_ROUTE( 91096825bebSEd Tanous app, 91196825bebSEd Tanous "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia") 91296825bebSEd Tanous .privileges(redfish::privileges::postVirtualMedia) 91396825bebSEd Tanous .methods(boost::beast::http::verb::post)(std::bind_front( 91496825bebSEd Tanous handleManagersVirtualMediaActionInsertPost, std::ref(app))); 91596825bebSEd Tanous 91696825bebSEd Tanous BMCWEB_ROUTE( 91796825bebSEd Tanous app, 91896825bebSEd Tanous "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia") 91996825bebSEd Tanous .privileges(redfish::privileges::postVirtualMedia) 92096825bebSEd Tanous .methods(boost::beast::http::verb::post)(std::bind_front( 92196825bebSEd Tanous handleManagersVirtualMediaActionEject, std::ref(app))); 92296825bebSEd Tanous 92396825bebSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/") 92496825bebSEd Tanous .privileges(redfish::privileges::getVirtualMediaCollection) 92596825bebSEd Tanous .methods(boost::beast::http::verb::get)(std::bind_front( 92696825bebSEd Tanous handleManagersVirtualMediaCollectionGet, std::ref(app))); 92796825bebSEd Tanous 92896825bebSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/") 92996825bebSEd Tanous .privileges(redfish::privileges::getVirtualMedia) 93096825bebSEd Tanous .methods(boost::beast::http::verb::get)( 93196825bebSEd Tanous std::bind_front(handleVirtualMediaGet, std::ref(app))); 932107077deSPrzemyslaw Czarnowski } 933107077deSPrzemyslaw Czarnowski 934107077deSPrzemyslaw Czarnowski } // namespace redfish 935