140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 340e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation 4107077deSPrzemyslaw Czarnowski #pragma once 5107077deSPrzemyslaw Czarnowski 63ccb3adbSEd Tanous #include "app.hpp" 779fdf63eSPrzemyslaw Czarnowski #include "async_resp.hpp" 811e8f60dSEd Tanous #include "credential_pipe.hpp" 9d7857201SEd Tanous #include "dbus_singleton.hpp" 102b73119cSGeorge Liu #include "dbus_utility.hpp" 11d7857201SEd Tanous #include "error_messages.hpp" 12739b87efSEd Tanous #include "generated/enums/virtual_media.hpp" 13d7857201SEd Tanous #include "http_request.hpp" 14d7857201SEd Tanous #include "logging.hpp" 153ccb3adbSEd Tanous #include "query.hpp" 163ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 173ccb3adbSEd Tanous #include "utils/json_utils.hpp" 183ccb3adbSEd Tanous 19d7857201SEd Tanous #include <boost/beast/http/status.hpp> 20d7857201SEd Tanous #include <boost/beast/http/verb.hpp> 21d7857201SEd Tanous #include <boost/system/result.hpp> 22ef4c65b7SEd Tanous #include <boost/url/format.hpp> 23d7857201SEd Tanous #include <boost/url/parse.hpp> 249e319cf0SAnna Platash #include <boost/url/url_view.hpp> 254a7fbefdSEd Tanous #include <boost/url/url_view_base.hpp> 26d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp> 27107077deSPrzemyslaw Czarnowski 28d7857201SEd Tanous #include <cstddef> 294bbf2a13SEd Tanous #include <cstdint> 30d7857201SEd Tanous #include <filesystem> 31d7857201SEd Tanous #include <functional> 32d7857201SEd Tanous #include <memory> 33d7857201SEd Tanous #include <optional> 343544d2a7SEd Tanous #include <ranges> 35d7857201SEd Tanous #include <string> 362b73119cSGeorge Liu #include <string_view> 37d7857201SEd Tanous #include <utility> 38d7857201SEd Tanous #include <variant> 392b73119cSGeorge Liu 40107077deSPrzemyslaw Czarnowski namespace redfish 41107077deSPrzemyslaw Czarnowski { 42365a73f4SEd Tanous 43365a73f4SEd Tanous enum class VmMode 44365a73f4SEd Tanous { 45365a73f4SEd Tanous Invalid, 46365a73f4SEd Tanous Legacy, 47365a73f4SEd Tanous Proxy 48365a73f4SEd Tanous }; 49365a73f4SEd Tanous 50bd79bce8SPatrick Williams inline VmMode parseObjectPathAndGetMode( 51bd79bce8SPatrick Williams const sdbusplus::message::object_path& itemPath, const std::string& resName) 52365a73f4SEd Tanous { 53365a73f4SEd Tanous std::string thisPath = itemPath.filename(); 5462598e31SEd Tanous BMCWEB_LOG_DEBUG("Filename: {}, ThisPath: {}", itemPath.str, thisPath); 55365a73f4SEd Tanous 56365a73f4SEd Tanous if (thisPath.empty()) 57365a73f4SEd Tanous { 58365a73f4SEd Tanous return VmMode::Invalid; 59365a73f4SEd Tanous } 60365a73f4SEd Tanous 61365a73f4SEd Tanous if (thisPath != resName) 62365a73f4SEd Tanous { 63365a73f4SEd Tanous return VmMode::Invalid; 64365a73f4SEd Tanous } 65365a73f4SEd Tanous 66365a73f4SEd Tanous auto mode = itemPath.parent_path(); 67365a73f4SEd Tanous auto type = mode.parent_path(); 68365a73f4SEd Tanous 69365a73f4SEd Tanous if (mode.filename().empty() || type.filename().empty()) 70365a73f4SEd Tanous { 71365a73f4SEd Tanous return VmMode::Invalid; 72365a73f4SEd Tanous } 73365a73f4SEd Tanous 74365a73f4SEd Tanous if (type.filename() != "VirtualMedia") 75365a73f4SEd Tanous { 76365a73f4SEd Tanous return VmMode::Invalid; 77365a73f4SEd Tanous } 78365a73f4SEd Tanous std::string modeStr = mode.filename(); 79365a73f4SEd Tanous if (modeStr == "Legacy") 80365a73f4SEd Tanous { 81365a73f4SEd Tanous return VmMode::Legacy; 82365a73f4SEd Tanous } 83365a73f4SEd Tanous if (modeStr == "Proxy") 84365a73f4SEd Tanous { 85365a73f4SEd Tanous return VmMode::Proxy; 86365a73f4SEd Tanous } 87365a73f4SEd Tanous return VmMode::Invalid; 88365a73f4SEd Tanous } 89365a73f4SEd Tanous 9079fdf63eSPrzemyslaw Czarnowski using CheckItemHandler = 9179fdf63eSPrzemyslaw Czarnowski std::function<void(const std::string& service, const std::string& resName, 9279fdf63eSPrzemyslaw Czarnowski const std::shared_ptr<bmcweb::AsyncResp>&, 9370cbdf53SGeorge Liu const std::pair<sdbusplus::message::object_path, 9480f79a40SMichael Shen dbus::utility::DBusInterfacesMap>&)>; 9579fdf63eSPrzemyslaw Czarnowski 96504af5a0SPatrick Williams inline void findAndParseObject( 97504af5a0SPatrick Williams const std::string& service, const std::string& resName, 98ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9979fdf63eSPrzemyslaw Czarnowski CheckItemHandler&& handler) 10079fdf63eSPrzemyslaw Czarnowski { 1015eb468daSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/VirtualMedia"); 1025eb468daSGeorge Liu dbus::utility::getManagedObjects( 1035eb468daSGeorge Liu service, path, 1048cb2c024SEd Tanous [service, resName, asyncResp, handler = std::move(handler)]( 1058cb2c024SEd Tanous const boost::system::error_code& ec, 10670cbdf53SGeorge Liu const dbus::utility::ManagedObjectType& subtree) { 10779fdf63eSPrzemyslaw Czarnowski if (ec) 10879fdf63eSPrzemyslaw Czarnowski { 10962598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 11079fdf63eSPrzemyslaw Czarnowski 11179fdf63eSPrzemyslaw Czarnowski return; 11279fdf63eSPrzemyslaw Czarnowski } 11379fdf63eSPrzemyslaw Czarnowski 11470cbdf53SGeorge Liu for (const auto& item : subtree) 11579fdf63eSPrzemyslaw Czarnowski { 11679fdf63eSPrzemyslaw Czarnowski VmMode mode = parseObjectPathAndGetMode(item.first, resName); 11779fdf63eSPrzemyslaw Czarnowski if (mode != VmMode::Invalid) 11879fdf63eSPrzemyslaw Czarnowski { 119ac106bf6SEd Tanous handler(service, resName, asyncResp, item); 12079fdf63eSPrzemyslaw Czarnowski return; 12179fdf63eSPrzemyslaw Czarnowski } 12279fdf63eSPrzemyslaw Czarnowski } 12379fdf63eSPrzemyslaw Czarnowski 12462598e31SEd Tanous BMCWEB_LOG_DEBUG("Parent item not found"); 125ac106bf6SEd Tanous asyncResp->res.result(boost::beast::http::status::not_found); 1265eb468daSGeorge Liu }); 12779fdf63eSPrzemyslaw Czarnowski } 12879fdf63eSPrzemyslaw Czarnowski 1299e319cf0SAnna Platash /** 1309e319cf0SAnna Platash * @brief Function extracts transfer protocol name from URI. 1319e319cf0SAnna Platash */ 13267df073bSEd Tanous inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri) 13367df073bSEd Tanous { 1346fd29553SEd Tanous boost::system::result<boost::urls::url_view> url = 135079360aeSEd Tanous boost::urls::parse_uri(imageUri); 13667df073bSEd Tanous if (!url) 13767df073bSEd Tanous { 13867df073bSEd Tanous return "None"; 13967df073bSEd Tanous } 140079360aeSEd Tanous std::string_view scheme = url->scheme(); 14167df073bSEd Tanous if (scheme == "smb") 14267df073bSEd Tanous { 14367df073bSEd Tanous return "CIFS"; 14467df073bSEd Tanous } 14567df073bSEd Tanous if (scheme == "https") 14667df073bSEd Tanous { 14767df073bSEd Tanous return "HTTPS"; 14867df073bSEd Tanous } 14967df073bSEd Tanous 15067df073bSEd Tanous return "None"; 15167df073bSEd Tanous } 152107077deSPrzemyslaw Czarnowski 153107077deSPrzemyslaw Czarnowski /** 154107077deSPrzemyslaw Czarnowski * @brief Read all known properties from VM object interfaces 155107077deSPrzemyslaw Czarnowski */ 156504af5a0SPatrick Williams inline void vmParseInterfaceObject( 157504af5a0SPatrick Williams const dbus::utility::DBusInterfacesMap& interfaces, 158ac106bf6SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 159107077deSPrzemyslaw Czarnowski { 1608a592810SEd Tanous for (const auto& [interface, values] : interfaces) 161107077deSPrzemyslaw Czarnowski { 162711ac7a9SEd Tanous if (interface == "xyz.openbmc_project.VirtualMedia.MountPoint") 163107077deSPrzemyslaw Czarnowski { 164711ac7a9SEd Tanous for (const auto& [property, value] : values) 165107077deSPrzemyslaw Czarnowski { 166711ac7a9SEd Tanous if (property == "EndpointId") 167107077deSPrzemyslaw Czarnowski { 168107077deSPrzemyslaw Czarnowski const std::string* endpointIdValue = 169711ac7a9SEd Tanous std::get_if<std::string>(&value); 170711ac7a9SEd Tanous if (endpointIdValue == nullptr) 171107077deSPrzemyslaw Czarnowski { 172711ac7a9SEd Tanous continue; 173711ac7a9SEd Tanous } 174107077deSPrzemyslaw Czarnowski if (!endpointIdValue->empty()) 175107077deSPrzemyslaw Czarnowski { 176107077deSPrzemyslaw Czarnowski // Proxy mode 177ac106bf6SEd Tanous asyncResp->res 178711ac7a9SEd Tanous .jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] = 179d04ba325SPrzemyslaw Czarnowski *endpointIdValue; 180ac106bf6SEd Tanous asyncResp->res.jsonValue["TransferProtocolType"] = 181ac106bf6SEd Tanous "OEM"; 182107077deSPrzemyslaw Czarnowski } 183107077deSPrzemyslaw Czarnowski } 184711ac7a9SEd Tanous if (property == "ImageURL") 185107077deSPrzemyslaw Czarnowski { 186107077deSPrzemyslaw Czarnowski const std::string* imageUrlValue = 187711ac7a9SEd Tanous std::get_if<std::string>(&value); 18826f6976fSEd Tanous if (imageUrlValue != nullptr && !imageUrlValue->empty()) 189107077deSPrzemyslaw Czarnowski { 190da4784d8SPrzemyslaw Czarnowski std::filesystem::path filePath = *imageUrlValue; 191da4784d8SPrzemyslaw Czarnowski if (!filePath.has_filename()) 192da4784d8SPrzemyslaw Czarnowski { 1939e319cf0SAnna Platash // this will handle https share, which not 1949e319cf0SAnna Platash // necessarily has to have filename given. 195ac106bf6SEd Tanous asyncResp->res.jsonValue["ImageName"] = ""; 196da4784d8SPrzemyslaw Czarnowski } 197da4784d8SPrzemyslaw Czarnowski else 198da4784d8SPrzemyslaw Czarnowski { 199ac106bf6SEd Tanous asyncResp->res.jsonValue["ImageName"] = 2009e319cf0SAnna Platash filePath.filename(); 201da4784d8SPrzemyslaw Czarnowski } 202da4784d8SPrzemyslaw Czarnowski 203ac106bf6SEd Tanous asyncResp->res.jsonValue["Image"] = *imageUrlValue; 204ac106bf6SEd Tanous asyncResp->res.jsonValue["TransferProtocolType"] = 2059e319cf0SAnna Platash getTransferProtocolTypeFromUri(*imageUrlValue); 2069e319cf0SAnna Platash 207ac106bf6SEd Tanous asyncResp->res.jsonValue["ConnectedVia"] = 208739b87efSEd Tanous virtual_media::ConnectedVia::URI; 209107077deSPrzemyslaw Czarnowski } 210107077deSPrzemyslaw Czarnowski } 211711ac7a9SEd Tanous if (property == "WriteProtected") 2129e319cf0SAnna Platash { 213711ac7a9SEd Tanous const bool* writeProtectedValue = std::get_if<bool>(&value); 214e662eae8SEd Tanous if (writeProtectedValue != nullptr) 2159e319cf0SAnna Platash { 216ac106bf6SEd Tanous asyncResp->res.jsonValue["WriteProtected"] = 2179e319cf0SAnna Platash *writeProtectedValue; 2189e319cf0SAnna Platash } 2199e319cf0SAnna Platash } 2209e319cf0SAnna Platash } 221107077deSPrzemyslaw Czarnowski } 222711ac7a9SEd Tanous if (interface == "xyz.openbmc_project.VirtualMedia.Process") 223711ac7a9SEd Tanous { 224711ac7a9SEd Tanous for (const auto& [property, value] : values) 225711ac7a9SEd Tanous { 226711ac7a9SEd Tanous if (property == "Active") 227711ac7a9SEd Tanous { 228711ac7a9SEd Tanous const bool* activeValue = std::get_if<bool>(&value); 229e662eae8SEd Tanous if (activeValue == nullptr) 230711ac7a9SEd Tanous { 23162598e31SEd Tanous BMCWEB_LOG_DEBUG("Value Active not found"); 232711ac7a9SEd Tanous return; 233711ac7a9SEd Tanous } 234ac106bf6SEd Tanous asyncResp->res.jsonValue["Inserted"] = *activeValue; 235711ac7a9SEd Tanous 236e05aec50SEd Tanous if (*activeValue) 237711ac7a9SEd Tanous { 238ac106bf6SEd Tanous asyncResp->res.jsonValue["ConnectedVia"] = 239739b87efSEd Tanous virtual_media::ConnectedVia::Applet; 240711ac7a9SEd Tanous } 241711ac7a9SEd Tanous } 242711ac7a9SEd Tanous } 243711ac7a9SEd Tanous } 244107077deSPrzemyslaw Czarnowski } 245107077deSPrzemyslaw Czarnowski } 246107077deSPrzemyslaw Czarnowski 247107077deSPrzemyslaw Czarnowski /** 248107077deSPrzemyslaw Czarnowski * @brief Fill template for Virtual Media Item. 249107077deSPrzemyslaw Czarnowski */ 25022db1728SEd Tanous inline nlohmann::json vmItemTemplate(const std::string& name, 251107077deSPrzemyslaw Czarnowski const std::string& resName) 252107077deSPrzemyslaw Czarnowski { 253107077deSPrzemyslaw Czarnowski nlohmann::json item; 254ef4c65b7SEd Tanous item["@odata.id"] = boost::urls::format( 255ef4c65b7SEd Tanous "/redfish/v1/Managers/{}/VirtualMedia/{}", name, resName); 25622db1728SEd Tanous 257d04ba325SPrzemyslaw Czarnowski item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia"; 258107077deSPrzemyslaw Czarnowski item["Name"] = "Virtual Removable Media"; 259107077deSPrzemyslaw Czarnowski item["Id"] = resName; 260107077deSPrzemyslaw Czarnowski item["WriteProtected"] = true; 261739b87efSEd Tanous item["ConnectedVia"] = virtual_media::ConnectedVia::NotConnected; 262613dabeaSEd Tanous item["MediaTypes"] = nlohmann::json::array_t({"CD", "USBStick"}); 263539d8c6bSEd Tanous item["TransferMethod"] = virtual_media::TransferMethod::Stream; 264d04ba325SPrzemyslaw Czarnowski item["Oem"]["OpenBMC"]["@odata.type"] = 265f958ed9cSEd Tanous "#OpenBMCVirtualMedia.v1_0_0.VirtualMedia"; 26615b89725SV-Sanjana item["Oem"]["OpenBMC"]["@odata.id"] = boost::urls::format( 26715b89725SV-Sanjana "/redfish/v1/Managers/{}/VirtualMedia/{}#/Oem/OpenBMC", name, resName); 268107077deSPrzemyslaw Czarnowski 269107077deSPrzemyslaw Czarnowski return item; 270107077deSPrzemyslaw Czarnowski } 271107077deSPrzemyslaw Czarnowski 272107077deSPrzemyslaw Czarnowski /** 273107077deSPrzemyslaw Czarnowski * @brief Fills collection data 274107077deSPrzemyslaw Czarnowski */ 275ac106bf6SEd Tanous inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> asyncResp, 276107077deSPrzemyslaw Czarnowski const std::string& service, 277107077deSPrzemyslaw Czarnowski const std::string& name) 278107077deSPrzemyslaw Czarnowski { 27962598e31SEd Tanous BMCWEB_LOG_DEBUG("Get available Virtual Media resources."); 2805eb468daSGeorge Liu sdbusplus::message::object_path objPath( 2815eb468daSGeorge Liu "/xyz/openbmc_project/VirtualMedia"); 2825eb468daSGeorge Liu dbus::utility::getManagedObjects( 2835eb468daSGeorge Liu service, objPath, 284ac106bf6SEd Tanous [name, asyncResp{std::move(asyncResp)}]( 2855e7e2dc5SEd Tanous const boost::system::error_code& ec, 28602cad96eSEd Tanous const dbus::utility::ManagedObjectType& subtree) { 287107077deSPrzemyslaw Czarnowski if (ec) 288107077deSPrzemyslaw Czarnowski { 28962598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error"); 290107077deSPrzemyslaw Czarnowski return; 291107077deSPrzemyslaw Czarnowski } 292ac106bf6SEd Tanous nlohmann::json& members = asyncResp->res.jsonValue["Members"]; 293107077deSPrzemyslaw Czarnowski members = nlohmann::json::array(); 294107077deSPrzemyslaw Czarnowski 295107077deSPrzemyslaw Czarnowski for (const auto& object : subtree) 296107077deSPrzemyslaw Czarnowski { 297107077deSPrzemyslaw Czarnowski nlohmann::json item; 2982dfd18efSEd Tanous std::string path = object.first.filename(); 2992dfd18efSEd Tanous if (path.empty()) 300107077deSPrzemyslaw Czarnowski { 301107077deSPrzemyslaw Czarnowski continue; 302107077deSPrzemyslaw Czarnowski } 303107077deSPrzemyslaw Czarnowski 304ef4c65b7SEd Tanous item["@odata.id"] = boost::urls::format( 305ef4c65b7SEd Tanous "/redfish/v1/Managers/{}/VirtualMedia/{}", name, path); 306107077deSPrzemyslaw Czarnowski members.emplace_back(std::move(item)); 307107077deSPrzemyslaw Czarnowski } 308ac106bf6SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = members.size(); 3095eb468daSGeorge Liu }); 310107077deSPrzemyslaw Czarnowski } 311107077deSPrzemyslaw Czarnowski 312504af5a0SPatrick Williams inline void afterGetVmData( 313504af5a0SPatrick Williams const std::string& name, const std::string& /*service*/, 31479fdf63eSPrzemyslaw Czarnowski const std::string& resName, 31579fdf63eSPrzemyslaw Czarnowski const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 31670cbdf53SGeorge Liu const std::pair<sdbusplus::message::object_path, 31780f79a40SMichael Shen dbus::utility::DBusInterfacesMap>& item) 31879fdf63eSPrzemyslaw Czarnowski { 31979fdf63eSPrzemyslaw Czarnowski VmMode mode = parseObjectPathAndGetMode(item.first, resName); 32079fdf63eSPrzemyslaw Czarnowski if (mode == VmMode::Invalid) 32179fdf63eSPrzemyslaw Czarnowski { 32279fdf63eSPrzemyslaw Czarnowski return; 32379fdf63eSPrzemyslaw Czarnowski } 32479fdf63eSPrzemyslaw Czarnowski 32579fdf63eSPrzemyslaw Czarnowski asyncResp->res.jsonValue = vmItemTemplate(name, resName); 32679fdf63eSPrzemyslaw Czarnowski 32779fdf63eSPrzemyslaw Czarnowski // Check if dbus path is Legacy type 32879fdf63eSPrzemyslaw Czarnowski if (mode == VmMode::Legacy) 32979fdf63eSPrzemyslaw Czarnowski { 330ef4c65b7SEd Tanous asyncResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"] 331ef4c65b7SEd Tanous ["target"] = boost::urls::format( 332ef4c65b7SEd Tanous "/redfish/v1/Managers/{}/VirtualMedia/{}/Actions/VirtualMedia.InsertMedia", 333ef4c65b7SEd Tanous name, resName); 33479fdf63eSPrzemyslaw Czarnowski } 33579fdf63eSPrzemyslaw Czarnowski 33679fdf63eSPrzemyslaw Czarnowski vmParseInterfaceObject(item.second, asyncResp); 33779fdf63eSPrzemyslaw Czarnowski 338ef4c65b7SEd Tanous asyncResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"] 339ef4c65b7SEd Tanous ["target"] = boost::urls::format( 340ef4c65b7SEd Tanous "/redfish/v1/Managers/{}/VirtualMedia/{}/Actions/VirtualMedia.EjectMedia", 341ef4c65b7SEd Tanous name, resName); 34279fdf63eSPrzemyslaw Czarnowski } 34379fdf63eSPrzemyslaw Czarnowski 344107077deSPrzemyslaw Czarnowski /** 345107077deSPrzemyslaw Czarnowski * @brief Fills data for specific resource 346107077deSPrzemyslaw Czarnowski */ 347ac106bf6SEd Tanous inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 348107077deSPrzemyslaw Czarnowski const std::string& service, const std::string& name, 349107077deSPrzemyslaw Czarnowski const std::string& resName) 350107077deSPrzemyslaw Czarnowski { 35162598e31SEd Tanous BMCWEB_LOG_DEBUG("Get Virtual Media resource data."); 352107077deSPrzemyslaw Czarnowski 353ac106bf6SEd Tanous findAndParseObject(service, resName, asyncResp, 35470cbdf53SGeorge Liu std::bind_front(afterGetVmData, name)); 355107077deSPrzemyslaw Czarnowski } 356107077deSPrzemyslaw Czarnowski 357e13c2760SPrzemyslaw Czarnowski /** 358c6f4e017SAgata Olender * @brief Transfer protocols supported for InsertMedia action. 359c6f4e017SAgata Olender * 360c6f4e017SAgata Olender */ 361c6f4e017SAgata Olender enum class TransferProtocol 362c6f4e017SAgata Olender { 363c6f4e017SAgata Olender https, 364c6f4e017SAgata Olender smb, 365c6f4e017SAgata Olender invalid 366c6f4e017SAgata Olender }; 367c6f4e017SAgata Olender 368c6f4e017SAgata Olender /** 369c6f4e017SAgata Olender * @brief Function extracts transfer protocol type from URI. 370c6f4e017SAgata Olender * 371c6f4e017SAgata Olender */ 372504af5a0SPatrick Williams inline std::optional<TransferProtocol> getTransferProtocolFromUri( 373504af5a0SPatrick Williams const boost::urls::url_view_base& imageUri) 37467df073bSEd Tanous { 375079360aeSEd Tanous std::string_view scheme = imageUri.scheme(); 37667df073bSEd Tanous if (scheme == "smb") 37767df073bSEd Tanous { 37867df073bSEd Tanous return TransferProtocol::smb; 37967df073bSEd Tanous } 38067df073bSEd Tanous if (scheme == "https") 38167df073bSEd Tanous { 38267df073bSEd Tanous return TransferProtocol::https; 38367df073bSEd Tanous } 38467df073bSEd Tanous if (!scheme.empty()) 38567df073bSEd Tanous { 38667df073bSEd Tanous return TransferProtocol::invalid; 38767df073bSEd Tanous } 38867df073bSEd Tanous 38967df073bSEd Tanous return {}; 39067df073bSEd Tanous } 391c6f4e017SAgata Olender 392c6f4e017SAgata Olender /** 393c6f4e017SAgata Olender * @brief Function convert transfer protocol from string param. 394c6f4e017SAgata Olender * 395c6f4e017SAgata Olender */ 39622db1728SEd Tanous inline std::optional<TransferProtocol> getTransferProtocolFromParam( 397c6f4e017SAgata Olender const std::optional<std::string>& transferProtocolType) 398c6f4e017SAgata Olender { 399e01d0c36SEd Tanous if (!transferProtocolType) 400c6f4e017SAgata Olender { 401c6f4e017SAgata Olender return {}; 402c6f4e017SAgata Olender } 403c6f4e017SAgata Olender 404c6f4e017SAgata Olender if (*transferProtocolType == "CIFS") 405c6f4e017SAgata Olender { 406c6f4e017SAgata Olender return TransferProtocol::smb; 407c6f4e017SAgata Olender } 408c6f4e017SAgata Olender 409c6f4e017SAgata Olender if (*transferProtocolType == "HTTPS") 410c6f4e017SAgata Olender { 411c6f4e017SAgata Olender return TransferProtocol::https; 412c6f4e017SAgata Olender } 413c6f4e017SAgata Olender 414c6f4e017SAgata Olender return TransferProtocol::invalid; 415c6f4e017SAgata Olender } 416c6f4e017SAgata Olender 417c6f4e017SAgata Olender /** 418c6f4e017SAgata Olender * @brief Function extends URI with transfer protocol type. 419c6f4e017SAgata Olender * 420c6f4e017SAgata Olender */ 421bd79bce8SPatrick Williams inline std::string getUriWithTransferProtocol( 422bd79bce8SPatrick Williams const std::string& imageUri, const TransferProtocol& transferProtocol) 423c6f4e017SAgata Olender { 424c6f4e017SAgata Olender if (transferProtocol == TransferProtocol::smb) 425c6f4e017SAgata Olender { 426c6f4e017SAgata Olender return "smb://" + imageUri; 427c6f4e017SAgata Olender } 428c6f4e017SAgata Olender 429c6f4e017SAgata Olender if (transferProtocol == TransferProtocol::https) 430c6f4e017SAgata Olender { 431c6f4e017SAgata Olender return "https://" + imageUri; 432c6f4e017SAgata Olender } 433c6f4e017SAgata Olender 434c6f4e017SAgata Olender return imageUri; 435c6f4e017SAgata Olender } 436c6f4e017SAgata Olender 4371f2a40ceSPrzemyslaw Czarnowski struct InsertMediaActionParams 4381f2a40ceSPrzemyslaw Czarnowski { 439120fa86aSPrzemyslaw Czarnowski std::optional<std::string> imageUrl; 4401f2a40ceSPrzemyslaw Czarnowski std::optional<std::string> userName; 4411f2a40ceSPrzemyslaw Czarnowski std::optional<std::string> password; 4421f2a40ceSPrzemyslaw Czarnowski std::optional<std::string> transferMethod; 4431f2a40ceSPrzemyslaw Czarnowski std::optional<std::string> transferProtocolType; 4441f2a40ceSPrzemyslaw Czarnowski std::optional<bool> writeProtected = true; 4451f2a40ceSPrzemyslaw Czarnowski std::optional<bool> inserted; 4461f2a40ceSPrzemyslaw Czarnowski }; 4471f2a40ceSPrzemyslaw Czarnowski 448e13c2760SPrzemyslaw Czarnowski /** 449e13c2760SPrzemyslaw Czarnowski * @brief Function transceives data with dbus directly. 450e13c2760SPrzemyslaw Czarnowski * 451e13c2760SPrzemyslaw Czarnowski * All BMC state properties will be retrieved before sending reset request. 452e13c2760SPrzemyslaw Czarnowski */ 45322db1728SEd Tanous inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 454e13c2760SPrzemyslaw Czarnowski const std::string& service, const std::string& name, 45511e8f60dSEd Tanous const std::string& imageUrl, bool rw, 456988fb7b2SAdrian Ambrożewicz std::string&& userName, std::string&& password) 457e13c2760SPrzemyslaw Czarnowski { 4584bbf2a13SEd Tanous if (userName.contains('\0')) 459988fb7b2SAdrian Ambrożewicz { 4604bbf2a13SEd Tanous messages::actionParameterValueFormatError( 4614bbf2a13SEd Tanous asyncResp->res, userName, "Username", "VirtualMedia.InsertMedia"); 462988fb7b2SAdrian Ambrożewicz return; 463988fb7b2SAdrian Ambrożewicz } 4644bbf2a13SEd Tanous constexpr uint64_t limit = 512; 4654bbf2a13SEd Tanous if (userName.size() > limit) 4664bbf2a13SEd Tanous { 4674bbf2a13SEd Tanous messages::stringValueTooLong(asyncResp->res, userName, limit); 4684bbf2a13SEd Tanous return; 4694bbf2a13SEd Tanous } 4704bbf2a13SEd Tanous if (password.contains('\0')) 4714bbf2a13SEd Tanous { 4724bbf2a13SEd Tanous messages::actionParameterValueFormatError( 4734bbf2a13SEd Tanous asyncResp->res, password, "Password", "VirtualMedia.InsertMedia"); 4744bbf2a13SEd Tanous return; 4754bbf2a13SEd Tanous } 4764bbf2a13SEd Tanous if (password.size() > limit) 4774bbf2a13SEd Tanous { 4784bbf2a13SEd Tanous messages::stringValueTooLong(asyncResp->res, password, limit); 4794bbf2a13SEd Tanous return; 4804bbf2a13SEd Tanous } 481988fb7b2SAdrian Ambrożewicz // Open pipe 4824bbf2a13SEd Tanous std::shared_ptr<CredentialsPipe> secretPipe = 4834bbf2a13SEd Tanous std::make_shared<CredentialsPipe>( 48411e8f60dSEd Tanous crow::connections::systemBus->get_io_context()); 4854bbf2a13SEd Tanous int fd = secretPipe->releaseFd(); 486988fb7b2SAdrian Ambrożewicz 487988fb7b2SAdrian Ambrożewicz // Pass secret over pipe 48881ce609eSEd Tanous secretPipe->asyncWrite( 48911e8f60dSEd Tanous std::move(userName), std::move(password), 490bd79bce8SPatrick Williams [asyncResp, 491bd79bce8SPatrick Williams secretPipe](const boost::system::error_code& ec, std::size_t) { 492988fb7b2SAdrian Ambrożewicz if (ec) 493988fb7b2SAdrian Ambrożewicz { 49462598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to pass secret: {}", ec); 495988fb7b2SAdrian Ambrożewicz messages::internalError(asyncResp->res); 496988fb7b2SAdrian Ambrożewicz } 497988fb7b2SAdrian Ambrożewicz }); 498988fb7b2SAdrian Ambrożewicz 4994bbf2a13SEd Tanous sdbusplus::message::unix_fd unixFd(fd); 50011e8f60dSEd Tanous 50111e8f60dSEd Tanous sdbusplus::message::object_path path( 50211e8f60dSEd Tanous "/xyz/openbmc_project/VirtualMedia/Legacy"); 50311e8f60dSEd Tanous path /= name; 504*177612aaSEd Tanous dbus::utility::async_method_call( 505*177612aaSEd Tanous asyncResp, 5064bbf2a13SEd Tanous [asyncResp](const boost::system::error_code& ec, bool success) { 507e13c2760SPrzemyslaw Czarnowski if (ec) 508e13c2760SPrzemyslaw Czarnowski { 50962598e31SEd Tanous BMCWEB_LOG_ERROR("Bad D-Bus request error: {}", ec); 510e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 51111e8f60dSEd Tanous return; 512d6da5bebSAdrian Ambrożewicz } 51311e8f60dSEd Tanous if (!success) 514d6da5bebSAdrian Ambrożewicz { 51562598e31SEd Tanous BMCWEB_LOG_ERROR("Service responded with error"); 51611e8f60dSEd Tanous messages::internalError(asyncResp->res); 517e13c2760SPrzemyslaw Czarnowski } 518e13c2760SPrzemyslaw Czarnowski }, 51911e8f60dSEd Tanous service, path.str, "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", 52011e8f60dSEd Tanous imageUrl, rw, unixFd); 521e13c2760SPrzemyslaw Czarnowski } 522e13c2760SPrzemyslaw Czarnowski 523e13c2760SPrzemyslaw Czarnowski /** 524120fa86aSPrzemyslaw Czarnowski * @brief Function validate parameters of insert media request. 525120fa86aSPrzemyslaw Czarnowski * 526120fa86aSPrzemyslaw Czarnowski */ 527120fa86aSPrzemyslaw Czarnowski inline void validateParams(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 528120fa86aSPrzemyslaw Czarnowski const std::string& service, 529120fa86aSPrzemyslaw Czarnowski const std::string& resName, 530120fa86aSPrzemyslaw Czarnowski InsertMediaActionParams& actionParams) 531120fa86aSPrzemyslaw Czarnowski { 53262598e31SEd Tanous BMCWEB_LOG_DEBUG("Validation started"); 533120fa86aSPrzemyslaw Czarnowski // required param imageUrl must not be empty 534120fa86aSPrzemyslaw Czarnowski if (!actionParams.imageUrl) 535120fa86aSPrzemyslaw Czarnowski { 53662598e31SEd Tanous BMCWEB_LOG_ERROR("Request action parameter Image is empty."); 537120fa86aSPrzemyslaw Czarnowski 538120fa86aSPrzemyslaw Czarnowski messages::propertyValueFormatError(asyncResp->res, "<empty>", "Image"); 539120fa86aSPrzemyslaw Czarnowski 540120fa86aSPrzemyslaw Czarnowski return; 541120fa86aSPrzemyslaw Czarnowski } 542120fa86aSPrzemyslaw Czarnowski 543120fa86aSPrzemyslaw Czarnowski // optional param inserted must be true 544e01d0c36SEd Tanous if (actionParams.inserted && !*actionParams.inserted) 545120fa86aSPrzemyslaw Czarnowski { 54662598e31SEd Tanous BMCWEB_LOG_ERROR( 54762598e31SEd Tanous "Request action optional parameter Inserted must be true."); 548120fa86aSPrzemyslaw Czarnowski 549120fa86aSPrzemyslaw Czarnowski messages::actionParameterNotSupported(asyncResp->res, "Inserted", 550120fa86aSPrzemyslaw Czarnowski "InsertMedia"); 551120fa86aSPrzemyslaw Czarnowski 552120fa86aSPrzemyslaw Czarnowski return; 553120fa86aSPrzemyslaw Czarnowski } 554120fa86aSPrzemyslaw Czarnowski 555120fa86aSPrzemyslaw Czarnowski // optional param transferMethod must be stream 556e01d0c36SEd Tanous if (actionParams.transferMethod && 557120fa86aSPrzemyslaw Czarnowski (*actionParams.transferMethod != "Stream")) 558120fa86aSPrzemyslaw Czarnowski { 55962598e31SEd Tanous BMCWEB_LOG_ERROR("Request action optional parameter " 56062598e31SEd Tanous "TransferMethod must be Stream."); 561120fa86aSPrzemyslaw Czarnowski 562120fa86aSPrzemyslaw Czarnowski messages::actionParameterNotSupported(asyncResp->res, "TransferMethod", 563120fa86aSPrzemyslaw Czarnowski "InsertMedia"); 564120fa86aSPrzemyslaw Czarnowski 565120fa86aSPrzemyslaw Czarnowski return; 566120fa86aSPrzemyslaw Czarnowski } 5676fd29553SEd Tanous boost::system::result<boost::urls::url_view> url = 568120fa86aSPrzemyslaw Czarnowski boost::urls::parse_uri(*actionParams.imageUrl); 569120fa86aSPrzemyslaw Czarnowski if (!url) 570120fa86aSPrzemyslaw Czarnowski { 571120fa86aSPrzemyslaw Czarnowski messages::actionParameterValueFormatError( 572120fa86aSPrzemyslaw Czarnowski asyncResp->res, *actionParams.imageUrl, "Image", "InsertMedia"); 573120fa86aSPrzemyslaw Czarnowski return; 574120fa86aSPrzemyslaw Czarnowski } 575120fa86aSPrzemyslaw Czarnowski std::optional<TransferProtocol> uriTransferProtocolType = 576120fa86aSPrzemyslaw Czarnowski getTransferProtocolFromUri(*url); 577120fa86aSPrzemyslaw Czarnowski 578120fa86aSPrzemyslaw Czarnowski std::optional<TransferProtocol> paramTransferProtocolType = 579120fa86aSPrzemyslaw Czarnowski getTransferProtocolFromParam(actionParams.transferProtocolType); 580120fa86aSPrzemyslaw Czarnowski 581120fa86aSPrzemyslaw Czarnowski // ImageUrl does not contain valid protocol type 582e01d0c36SEd Tanous if (uriTransferProtocolType && 583e01d0c36SEd Tanous *uriTransferProtocolType == TransferProtocol::invalid) 584120fa86aSPrzemyslaw Czarnowski { 58562598e31SEd Tanous BMCWEB_LOG_ERROR("Request action parameter ImageUrl must " 586120fa86aSPrzemyslaw Czarnowski "contain specified protocol type from list: " 58762598e31SEd Tanous "(smb, https)."); 588120fa86aSPrzemyslaw Czarnowski 589120fa86aSPrzemyslaw Czarnowski messages::resourceAtUriInUnknownFormat(asyncResp->res, *url); 590120fa86aSPrzemyslaw Czarnowski 591120fa86aSPrzemyslaw Czarnowski return; 592120fa86aSPrzemyslaw Czarnowski } 593120fa86aSPrzemyslaw Czarnowski 594120fa86aSPrzemyslaw Czarnowski // transferProtocolType should contain value from list 595e01d0c36SEd Tanous if (paramTransferProtocolType && 596e01d0c36SEd Tanous *paramTransferProtocolType == TransferProtocol::invalid) 597120fa86aSPrzemyslaw Czarnowski { 59862598e31SEd Tanous BMCWEB_LOG_ERROR("Request action parameter TransferProtocolType " 599120fa86aSPrzemyslaw Czarnowski "must be provided with value from list: " 60062598e31SEd Tanous "(CIFS, HTTPS)."); 601120fa86aSPrzemyslaw Czarnowski 602e01d0c36SEd Tanous messages::propertyValueNotInList( 603e01d0c36SEd Tanous asyncResp->res, actionParams.transferProtocolType.value_or(""), 604120fa86aSPrzemyslaw Czarnowski "TransferProtocolType"); 605120fa86aSPrzemyslaw Czarnowski return; 606120fa86aSPrzemyslaw Czarnowski } 607120fa86aSPrzemyslaw Czarnowski 608120fa86aSPrzemyslaw Czarnowski // valid transfer protocol not provided either with URI nor param 609e01d0c36SEd Tanous if (!uriTransferProtocolType && !paramTransferProtocolType) 610120fa86aSPrzemyslaw Czarnowski { 61162598e31SEd Tanous BMCWEB_LOG_ERROR("Request action parameter ImageUrl must " 612120fa86aSPrzemyslaw Czarnowski "contain specified protocol type or param " 61362598e31SEd Tanous "TransferProtocolType must be provided."); 614120fa86aSPrzemyslaw Czarnowski 615120fa86aSPrzemyslaw Czarnowski messages::resourceAtUriInUnknownFormat(asyncResp->res, *url); 616120fa86aSPrzemyslaw Czarnowski 617120fa86aSPrzemyslaw Czarnowski return; 618120fa86aSPrzemyslaw Czarnowski } 619120fa86aSPrzemyslaw Czarnowski 620120fa86aSPrzemyslaw Czarnowski // valid transfer protocol provided both with URI and param 621e01d0c36SEd Tanous if (paramTransferProtocolType && uriTransferProtocolType) 622120fa86aSPrzemyslaw Czarnowski { 623120fa86aSPrzemyslaw Czarnowski // check if protocol is the same for URI and param 624120fa86aSPrzemyslaw Czarnowski if (*paramTransferProtocolType != *uriTransferProtocolType) 625120fa86aSPrzemyslaw Czarnowski { 62662598e31SEd Tanous BMCWEB_LOG_ERROR("Request action parameter " 627120fa86aSPrzemyslaw Czarnowski "TransferProtocolType must contain the " 628120fa86aSPrzemyslaw Czarnowski "same protocol type as protocol type " 62962598e31SEd Tanous "provided with param imageUrl."); 630120fa86aSPrzemyslaw Czarnowski 631120fa86aSPrzemyslaw Czarnowski messages::actionParameterValueTypeError( 632e01d0c36SEd Tanous asyncResp->res, actionParams.transferProtocolType.value_or(""), 633120fa86aSPrzemyslaw Czarnowski "TransferProtocolType", "InsertMedia"); 634120fa86aSPrzemyslaw Czarnowski 635120fa86aSPrzemyslaw Czarnowski return; 636120fa86aSPrzemyslaw Czarnowski } 637120fa86aSPrzemyslaw Czarnowski } 638120fa86aSPrzemyslaw Czarnowski 639120fa86aSPrzemyslaw Czarnowski // validation passed, add protocol to URI if needed 6407ead48e6SBoleslaw Ogonczyk Makowski if (!uriTransferProtocolType && paramTransferProtocolType) 641120fa86aSPrzemyslaw Czarnowski { 642120fa86aSPrzemyslaw Czarnowski actionParams.imageUrl = getUriWithTransferProtocol( 643120fa86aSPrzemyslaw Czarnowski *actionParams.imageUrl, *paramTransferProtocolType); 644120fa86aSPrzemyslaw Czarnowski } 645120fa86aSPrzemyslaw Czarnowski 646452bd8d8SJayaprakash Mutyala if (!actionParams.userName) 647452bd8d8SJayaprakash Mutyala { 648452bd8d8SJayaprakash Mutyala actionParams.userName = ""; 649452bd8d8SJayaprakash Mutyala } 650452bd8d8SJayaprakash Mutyala 651452bd8d8SJayaprakash Mutyala if (!actionParams.password) 652452bd8d8SJayaprakash Mutyala { 653452bd8d8SJayaprakash Mutyala actionParams.password = ""; 654452bd8d8SJayaprakash Mutyala } 655452bd8d8SJayaprakash Mutyala 656120fa86aSPrzemyslaw Czarnowski doMountVmLegacy(asyncResp, service, resName, *actionParams.imageUrl, 657e01d0c36SEd Tanous !(actionParams.writeProtected.value_or(false)), 658120fa86aSPrzemyslaw Czarnowski std::move(*actionParams.userName), 659120fa86aSPrzemyslaw Czarnowski std::move(*actionParams.password)); 660120fa86aSPrzemyslaw Czarnowski } 661120fa86aSPrzemyslaw Czarnowski 662120fa86aSPrzemyslaw Czarnowski /** 663e13c2760SPrzemyslaw Czarnowski * @brief Function transceives data with dbus directly. 664e13c2760SPrzemyslaw Czarnowski * 665e13c2760SPrzemyslaw Czarnowski * All BMC state properties will be retrieved before sending reset request. 666e13c2760SPrzemyslaw Czarnowski */ 66724e740a7SEd Tanous inline void doEjectAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 668e13c2760SPrzemyslaw Czarnowski const std::string& service, const std::string& name, 669e13c2760SPrzemyslaw Czarnowski bool legacy) 670e13c2760SPrzemyslaw Czarnowski { 671e13c2760SPrzemyslaw Czarnowski // Legacy mount requires parameter with image 672e13c2760SPrzemyslaw Czarnowski if (legacy) 673e13c2760SPrzemyslaw Czarnowski { 674*177612aaSEd Tanous dbus::utility::async_method_call( 675*177612aaSEd Tanous asyncResp, 6765e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 677e13c2760SPrzemyslaw Czarnowski if (ec) 678e13c2760SPrzemyslaw Czarnowski { 67962598e31SEd Tanous BMCWEB_LOG_ERROR("Bad D-Bus request error: {}", ec); 680e13c2760SPrzemyslaw Czarnowski 681e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 682e13c2760SPrzemyslaw Czarnowski return; 683e13c2760SPrzemyslaw Czarnowski } 684e13c2760SPrzemyslaw Czarnowski }, 685e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, 686e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount"); 687e13c2760SPrzemyslaw Czarnowski } 688e13c2760SPrzemyslaw Czarnowski else // proxy 689e13c2760SPrzemyslaw Czarnowski { 690*177612aaSEd Tanous dbus::utility::async_method_call( 691*177612aaSEd Tanous asyncResp, 6925e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 693e13c2760SPrzemyslaw Czarnowski if (ec) 694e13c2760SPrzemyslaw Czarnowski { 69562598e31SEd Tanous BMCWEB_LOG_ERROR("Bad D-Bus request error: {}", ec); 696e13c2760SPrzemyslaw Czarnowski 697e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 698e13c2760SPrzemyslaw Czarnowski return; 699e13c2760SPrzemyslaw Czarnowski } 700e13c2760SPrzemyslaw Czarnowski }, 701e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name, 702e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount"); 703e13c2760SPrzemyslaw Czarnowski } 704e13c2760SPrzemyslaw Czarnowski } 705e13c2760SPrzemyslaw Czarnowski 70696825bebSEd Tanous inline void handleManagersVirtualMediaActionInsertPost( 70796825bebSEd Tanous crow::App& app, const crow::Request& req, 70822db1728SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 70996825bebSEd Tanous const std::string& name, const std::string& resName) 71096825bebSEd Tanous { 7113ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 71245ca1b86SEd Tanous { 71345ca1b86SEd Tanous return; 71445ca1b86SEd Tanous } 71579fdf63eSPrzemyslaw Czarnowski 71679fdf63eSPrzemyslaw Czarnowski constexpr std::string_view action = "VirtualMedia.InsertMedia"; 71722db1728SEd Tanous if (name != "bmc") 718107077deSPrzemyslaw Czarnowski { 71979fdf63eSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, action, resName); 720107077deSPrzemyslaw Czarnowski 721107077deSPrzemyslaw Czarnowski return; 722107077deSPrzemyslaw Czarnowski } 72379fdf63eSPrzemyslaw Czarnowski InsertMediaActionParams actionParams; 72498be3e39SEd Tanous 725120fa86aSPrzemyslaw Czarnowski // Read obligatory parameters (url of image) 726afc474aeSMyung Bae if (!json_util::readJsonAction( // 727afc474aeSMyung Bae req, asyncResp->res, // 728afc474aeSMyung Bae "Image", actionParams.imageUrl, // 729afc474aeSMyung Bae "Inserted", actionParams.inserted, // 730afc474aeSMyung Bae "Password", actionParams.password, // 731afc474aeSMyung Bae "TransferMethod", actionParams.transferMethod, // 732afc474aeSMyung Bae "TransferProtocolType", actionParams.transferProtocolType, // 733afc474aeSMyung Bae "UserName", actionParams.userName, // 734afc474aeSMyung Bae "WriteProtected", actionParams.writeProtected // 735afc474aeSMyung Bae )) 73698be3e39SEd Tanous { 73798be3e39SEd Tanous return; 73898be3e39SEd Tanous } 739107077deSPrzemyslaw Czarnowski 7402b73119cSGeorge Liu dbus::utility::getDbusObject( 7412b73119cSGeorge Liu "/xyz/openbmc_project/VirtualMedia", {}, 74279fdf63eSPrzemyslaw Czarnowski [asyncResp, action, actionParams, 7432b73119cSGeorge Liu resName](const boost::system::error_code& ec, 744002d39b4SEd Tanous const dbus::utility::MapperGetObject& getObjectType) mutable { 74522db1728SEd Tanous if (ec) 74622db1728SEd Tanous { 74762598e31SEd Tanous BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", ec); 74879fdf63eSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, action, resName); 749107077deSPrzemyslaw Czarnowski 75022db1728SEd Tanous return; 75122db1728SEd Tanous } 75279fdf63eSPrzemyslaw Czarnowski 75322db1728SEd Tanous std::string service = getObjectType.begin()->first; 75462598e31SEd Tanous BMCWEB_LOG_DEBUG("GetObjectType: {}", service); 75522db1728SEd Tanous 7565eb468daSGeorge Liu sdbusplus::message::object_path path( 7575eb468daSGeorge Liu "/xyz/openbmc_project/VirtualMedia"); 7585eb468daSGeorge Liu dbus::utility::getManagedObjects( 7595eb468daSGeorge Liu service, path, 7605eb468daSGeorge Liu [service, resName, action, actionParams, asyncResp]( 7615eb468daSGeorge Liu const boost::system::error_code& ec2, 7625eb468daSGeorge Liu const dbus::utility::ManagedObjectType& subtree) mutable { 7638a592810SEd Tanous if (ec2) 76422db1728SEd Tanous { 76579fdf63eSPrzemyslaw Czarnowski // Not possible in proxy mode 76662598e31SEd Tanous BMCWEB_LOG_DEBUG("InsertMedia not " 76762598e31SEd Tanous "allowed in proxy mode"); 768bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, action, 769bd79bce8SPatrick Williams resName); 77022db1728SEd Tanous 77122db1728SEd Tanous return; 77222db1728SEd Tanous } 77322db1728SEd Tanous for (const auto& object : subtree) 77422db1728SEd Tanous { 775bd79bce8SPatrick Williams VmMode mode = 776bd79bce8SPatrick Williams parseObjectPathAndGetMode(object.first, resName); 7775880f0c5SBoleslaw Ogonczyk Makowski if (mode == VmMode::Legacy) 77822db1728SEd Tanous { 779bd79bce8SPatrick Williams validateParams(asyncResp, service, resName, 780bd79bce8SPatrick Williams actionParams); 78122db1728SEd Tanous 78222db1728SEd Tanous return; 78322db1728SEd Tanous } 78422db1728SEd Tanous } 78562598e31SEd Tanous BMCWEB_LOG_DEBUG("Parent item not found"); 786bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "VirtualMedia", 787bd79bce8SPatrick Williams resName); 7885eb468daSGeorge Liu }); 7892b73119cSGeorge Liu }); 79096825bebSEd Tanous } 79122db1728SEd Tanous 79296825bebSEd Tanous inline void handleManagersVirtualMediaActionEject( 79396825bebSEd Tanous crow::App& app, const crow::Request& req, 79422db1728SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 79596825bebSEd Tanous const std::string& managerName, const std::string& resName) 79696825bebSEd Tanous { 7973ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 79845ca1b86SEd Tanous { 79945ca1b86SEd Tanous return; 80045ca1b86SEd Tanous } 80179fdf63eSPrzemyslaw Czarnowski 80279fdf63eSPrzemyslaw Czarnowski constexpr std::string_view action = "VirtualMedia.EjectMedia"; 80396825bebSEd Tanous if (managerName != "bmc") 804107077deSPrzemyslaw Czarnowski { 80579fdf63eSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, action, resName); 80622db1728SEd Tanous 80722db1728SEd Tanous return; 80822db1728SEd Tanous } 80922db1728SEd Tanous 8102b73119cSGeorge Liu dbus::utility::getDbusObject( 8112b73119cSGeorge Liu "/xyz/openbmc_project/VirtualMedia", {}, 81279fdf63eSPrzemyslaw Czarnowski [asyncResp, action, 8132b73119cSGeorge Liu resName](const boost::system::error_code& ec2, 814b9d36b47SEd Tanous const dbus::utility::MapperGetObject& getObjectType) { 8158a592810SEd Tanous if (ec2) 81622db1728SEd Tanous { 817bd79bce8SPatrick Williams BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", 818bd79bce8SPatrick Williams ec2); 81922db1728SEd Tanous messages::internalError(asyncResp->res); 82022db1728SEd Tanous 82122db1728SEd Tanous return; 82222db1728SEd Tanous } 82322db1728SEd Tanous std::string service = getObjectType.begin()->first; 82462598e31SEd Tanous BMCWEB_LOG_DEBUG("GetObjectType: {}", service); 82522db1728SEd Tanous 8265eb468daSGeorge Liu sdbusplus::message::object_path path( 8275eb468daSGeorge Liu "/xyz/openbmc_project/VirtualMedia"); 8285eb468daSGeorge Liu dbus::utility::getManagedObjects( 8295eb468daSGeorge Liu service, path, 83079fdf63eSPrzemyslaw Czarnowski [resName, service, action, 83179fdf63eSPrzemyslaw Czarnowski asyncResp](const boost::system::error_code& ec, 83202cad96eSEd Tanous const dbus::utility::ManagedObjectType& subtree) { 83322db1728SEd Tanous if (ec) 83422db1728SEd Tanous { 83562598e31SEd Tanous BMCWEB_LOG_ERROR("ObjectMapper : No Service found"); 836bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, action, 837bd79bce8SPatrick Williams resName); 83822db1728SEd Tanous return; 83922db1728SEd Tanous } 84022db1728SEd Tanous 84122db1728SEd Tanous for (const auto& object : subtree) 84222db1728SEd Tanous { 843bd79bce8SPatrick Williams VmMode mode = 844bd79bce8SPatrick Williams parseObjectPathAndGetMode(object.first, resName); 845365a73f4SEd Tanous if (mode != VmMode::Invalid) 84622db1728SEd Tanous { 847365a73f4SEd Tanous doEjectAction(asyncResp, service, resName, 848365a73f4SEd Tanous mode == VmMode::Legacy); 8495880f0c5SBoleslaw Ogonczyk Makowski return; 85022db1728SEd Tanous } 85122db1728SEd Tanous } 85262598e31SEd Tanous BMCWEB_LOG_DEBUG("Parent item not found"); 853bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "VirtualMedia", 854bd79bce8SPatrick Williams resName); 8555eb468daSGeorge Liu }); 8562b73119cSGeorge Liu }); 85796825bebSEd Tanous } 85896825bebSEd Tanous 85996825bebSEd Tanous inline void handleManagersVirtualMediaCollectionGet( 86096825bebSEd Tanous crow::App& app, const crow::Request& req, 86122db1728SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 86296825bebSEd Tanous const std::string& name) 86396825bebSEd Tanous { 8643ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 86545ca1b86SEd Tanous { 86645ca1b86SEd Tanous return; 86745ca1b86SEd Tanous } 86822db1728SEd Tanous if (name != "bmc") 86922db1728SEd Tanous { 870002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "VirtualMedia", name); 871107077deSPrzemyslaw Czarnowski 872107077deSPrzemyslaw Czarnowski return; 873107077deSPrzemyslaw Czarnowski } 874107077deSPrzemyslaw Czarnowski 8758d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 876107077deSPrzemyslaw Czarnowski "#VirtualMediaCollection.VirtualMediaCollection"; 8778d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Virtual Media Services"; 878ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 879ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/VirtualMedia", name); 880107077deSPrzemyslaw Czarnowski 8812b73119cSGeorge Liu dbus::utility::getDbusObject( 8822b73119cSGeorge Liu "/xyz/openbmc_project/VirtualMedia", {}, 8832b73119cSGeorge Liu [asyncResp, name](const boost::system::error_code& ec, 884b9d36b47SEd Tanous const dbus::utility::MapperGetObject& getObjectType) { 885107077deSPrzemyslaw Czarnowski if (ec) 886107077deSPrzemyslaw Czarnowski { 88762598e31SEd Tanous BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", ec); 888107077deSPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 889107077deSPrzemyslaw Czarnowski 890107077deSPrzemyslaw Czarnowski return; 891107077deSPrzemyslaw Czarnowski } 892107077deSPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 89362598e31SEd Tanous BMCWEB_LOG_DEBUG("GetObjectType: {}", service); 894107077deSPrzemyslaw Czarnowski 895107077deSPrzemyslaw Czarnowski getVmResourceList(asyncResp, service, name); 8962b73119cSGeorge Liu }); 89796825bebSEd Tanous } 898107077deSPrzemyslaw Czarnowski 899504af5a0SPatrick Williams inline void handleVirtualMediaGet( 900504af5a0SPatrick Williams crow::App& app, const crow::Request& req, 90122db1728SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 90296825bebSEd Tanous const std::string& name, const std::string& resName) 90396825bebSEd Tanous { 9043ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 90545ca1b86SEd Tanous { 90645ca1b86SEd Tanous return; 90745ca1b86SEd Tanous } 908107077deSPrzemyslaw Czarnowski if (name != "bmc") 909107077deSPrzemyslaw Czarnowski { 910002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName); 911107077deSPrzemyslaw Czarnowski 912107077deSPrzemyslaw Czarnowski return; 913107077deSPrzemyslaw Czarnowski } 914107077deSPrzemyslaw Czarnowski 9152b73119cSGeorge Liu dbus::utility::getDbusObject( 9162b73119cSGeorge Liu "/xyz/openbmc_project/VirtualMedia", {}, 917002d39b4SEd Tanous [asyncResp, name, 9182b73119cSGeorge Liu resName](const boost::system::error_code& ec, 919b9d36b47SEd Tanous const dbus::utility::MapperGetObject& getObjectType) { 920107077deSPrzemyslaw Czarnowski if (ec) 921107077deSPrzemyslaw Czarnowski { 92262598e31SEd Tanous BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", ec); 923107077deSPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 924107077deSPrzemyslaw Czarnowski 925107077deSPrzemyslaw Czarnowski return; 926107077deSPrzemyslaw Czarnowski } 927107077deSPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 92862598e31SEd Tanous BMCWEB_LOG_DEBUG("GetObjectType: {}", service); 929107077deSPrzemyslaw Czarnowski 930107077deSPrzemyslaw Czarnowski getVmData(asyncResp, service, name, resName); 9312b73119cSGeorge Liu }); 93296825bebSEd Tanous } 93396825bebSEd Tanous 93496825bebSEd Tanous inline void requestNBDVirtualMediaRoutes(App& app) 93596825bebSEd Tanous { 93696825bebSEd Tanous BMCWEB_ROUTE( 93796825bebSEd Tanous app, 93896825bebSEd Tanous "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia") 93996825bebSEd Tanous .privileges(redfish::privileges::postVirtualMedia) 94096825bebSEd Tanous .methods(boost::beast::http::verb::post)(std::bind_front( 94196825bebSEd Tanous handleManagersVirtualMediaActionInsertPost, std::ref(app))); 94296825bebSEd Tanous 94396825bebSEd Tanous BMCWEB_ROUTE( 94496825bebSEd Tanous app, 94596825bebSEd Tanous "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia") 94696825bebSEd Tanous .privileges(redfish::privileges::postVirtualMedia) 94796825bebSEd Tanous .methods(boost::beast::http::verb::post)(std::bind_front( 94896825bebSEd Tanous handleManagersVirtualMediaActionEject, std::ref(app))); 94996825bebSEd Tanous 95096825bebSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/") 95196825bebSEd Tanous .privileges(redfish::privileges::getVirtualMediaCollection) 95296825bebSEd Tanous .methods(boost::beast::http::verb::get)(std::bind_front( 95396825bebSEd Tanous handleManagersVirtualMediaCollectionGet, std::ref(app))); 95496825bebSEd Tanous 95596825bebSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/") 95696825bebSEd Tanous .privileges(redfish::privileges::getVirtualMedia) 95796825bebSEd Tanous .methods(boost::beast::http::verb::get)( 95896825bebSEd Tanous std::bind_front(handleVirtualMediaGet, std::ref(app))); 959107077deSPrzemyslaw Czarnowski } 960107077deSPrzemyslaw Czarnowski 961107077deSPrzemyslaw Czarnowski } // namespace redfish 962