1107077deSPrzemyslaw Czarnowski /* 2107077deSPrzemyslaw Czarnowski // Copyright (c) 2018 Intel Corporation 3107077deSPrzemyslaw Czarnowski // 4107077deSPrzemyslaw Czarnowski // Licensed under the Apache License, Version 2.0 (the "License"); 5107077deSPrzemyslaw Czarnowski // you may not use this file except in compliance with the License. 6107077deSPrzemyslaw Czarnowski // You may obtain a copy of the License at 7107077deSPrzemyslaw Czarnowski // 8107077deSPrzemyslaw Czarnowski // http://www.apache.org/licenses/LICENSE-2.0 9107077deSPrzemyslaw Czarnowski // 10107077deSPrzemyslaw Czarnowski // Unless required by applicable law or agreed to in writing, software 11107077deSPrzemyslaw Czarnowski // distributed under the License is distributed on an "AS IS" BASIS, 12107077deSPrzemyslaw Czarnowski // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13107077deSPrzemyslaw Czarnowski // See the License for the specific language governing permissions and 14107077deSPrzemyslaw Czarnowski // limitations under the License. 15107077deSPrzemyslaw Czarnowski */ 16107077deSPrzemyslaw Czarnowski #pragma once 17107077deSPrzemyslaw Czarnowski 18107077deSPrzemyslaw Czarnowski #include <boost/container/flat_map.hpp> 19988fb7b2SAdrian Ambrożewicz #include <boost/process/async_pipe.hpp> 20988fb7b2SAdrian Ambrożewicz #include <boost/type_traits/has_dereference.hpp> 21107077deSPrzemyslaw Czarnowski #include <node.hpp> 22107077deSPrzemyslaw Czarnowski #include <utils/json_utils.hpp> 23107077deSPrzemyslaw Czarnowski // for GetObjectType and ManagedObjectType 24e13c2760SPrzemyslaw Czarnowski #include <account_service.hpp> 259e319cf0SAnna Platash #include <boost/url/url_view.hpp> 26107077deSPrzemyslaw Czarnowski 27107077deSPrzemyslaw Czarnowski namespace redfish 28107077deSPrzemyslaw Czarnowski 29107077deSPrzemyslaw Czarnowski { 309e319cf0SAnna Platash /** 319e319cf0SAnna Platash * @brief Function extracts transfer protocol name from URI. 329e319cf0SAnna Platash */ 339e319cf0SAnna Platash static std::string getTransferProtocolTypeFromUri(const std::string& imageUri) 349e319cf0SAnna Platash { 359e319cf0SAnna Platash try 369e319cf0SAnna Platash { 379e319cf0SAnna Platash std::string_view scheme = boost::urls::url_view(imageUri).scheme(); 389e319cf0SAnna Platash if (scheme == "smb") 399e319cf0SAnna Platash { 409e319cf0SAnna Platash return "CIFS"; 419e319cf0SAnna Platash } 429e319cf0SAnna Platash else if (scheme == "https") 439e319cf0SAnna Platash { 449e319cf0SAnna Platash return "HTTPS"; 459e319cf0SAnna Platash } 469e319cf0SAnna Platash } 479e319cf0SAnna Platash catch (std::exception& p) 489e319cf0SAnna Platash { 499e319cf0SAnna Platash BMCWEB_LOG_ERROR << p.what(); 509e319cf0SAnna Platash } 519e319cf0SAnna Platash return "None"; 529e319cf0SAnna Platash } 53107077deSPrzemyslaw Czarnowski 54107077deSPrzemyslaw Czarnowski /** 55107077deSPrzemyslaw Czarnowski * @brief Read all known properties from VM object interfaces 56107077deSPrzemyslaw Czarnowski */ 578d1b46d7Szhanghch05 static void 588d1b46d7Szhanghch05 vmParseInterfaceObject(const DbusInterfaceType& interface, 598d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& aResp) 60107077deSPrzemyslaw Czarnowski { 61107077deSPrzemyslaw Czarnowski const auto mountPointIface = 62107077deSPrzemyslaw Czarnowski interface.find("xyz.openbmc_project.VirtualMedia.MountPoint"); 63107077deSPrzemyslaw Czarnowski if (mountPointIface == interface.cend()) 64107077deSPrzemyslaw Czarnowski { 65107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Interface MountPoint not found"; 66107077deSPrzemyslaw Czarnowski return; 67107077deSPrzemyslaw Czarnowski } 68107077deSPrzemyslaw Czarnowski 69107077deSPrzemyslaw Czarnowski const auto processIface = 70107077deSPrzemyslaw Czarnowski interface.find("xyz.openbmc_project.VirtualMedia.Process"); 71107077deSPrzemyslaw Czarnowski if (processIface == interface.cend()) 72107077deSPrzemyslaw Czarnowski { 73107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Interface Process not found"; 74107077deSPrzemyslaw Czarnowski return; 75107077deSPrzemyslaw Czarnowski } 76107077deSPrzemyslaw Czarnowski 77107077deSPrzemyslaw Czarnowski const auto endpointIdProperty = mountPointIface->second.find("EndpointId"); 78107077deSPrzemyslaw Czarnowski if (endpointIdProperty == mountPointIface->second.cend()) 79107077deSPrzemyslaw Czarnowski { 80107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Property EndpointId not found"; 81107077deSPrzemyslaw Czarnowski return; 82107077deSPrzemyslaw Czarnowski } 83107077deSPrzemyslaw Czarnowski 84107077deSPrzemyslaw Czarnowski const auto activeProperty = processIface->second.find("Active"); 85107077deSPrzemyslaw Czarnowski if (activeProperty == processIface->second.cend()) 86107077deSPrzemyslaw Czarnowski { 87107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Property Active not found"; 88107077deSPrzemyslaw Czarnowski return; 89107077deSPrzemyslaw Czarnowski } 90107077deSPrzemyslaw Czarnowski 91107077deSPrzemyslaw Czarnowski const bool* activeValue = std::get_if<bool>(&activeProperty->second); 92107077deSPrzemyslaw Czarnowski if (!activeValue) 93107077deSPrzemyslaw Czarnowski { 94107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Value Active not found"; 95107077deSPrzemyslaw Czarnowski return; 96107077deSPrzemyslaw Czarnowski } 97107077deSPrzemyslaw Czarnowski 98107077deSPrzemyslaw Czarnowski const std::string* endpointIdValue = 99107077deSPrzemyslaw Czarnowski std::get_if<std::string>(&endpointIdProperty->second); 100107077deSPrzemyslaw Czarnowski if (endpointIdValue) 101107077deSPrzemyslaw Czarnowski { 102107077deSPrzemyslaw Czarnowski if (!endpointIdValue->empty()) 103107077deSPrzemyslaw Czarnowski { 104107077deSPrzemyslaw Czarnowski // Proxy mode 105d04ba325SPrzemyslaw Czarnowski aResp->res.jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] = 106d04ba325SPrzemyslaw Czarnowski *endpointIdValue; 107107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["TransferProtocolType"] = "OEM"; 108107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Inserted"] = *activeValue; 109107077deSPrzemyslaw Czarnowski if (*activeValue == true) 110107077deSPrzemyslaw Czarnowski { 111107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["ConnectedVia"] = "Applet"; 112107077deSPrzemyslaw Czarnowski } 113107077deSPrzemyslaw Czarnowski } 114107077deSPrzemyslaw Czarnowski else 115107077deSPrzemyslaw Czarnowski { 116107077deSPrzemyslaw Czarnowski // Legacy mode 1179e319cf0SAnna Platash for (const auto& property : mountPointIface->second) 1189e319cf0SAnna Platash { 1199e319cf0SAnna Platash if (property.first == "ImageURL") 120107077deSPrzemyslaw Czarnowski { 121107077deSPrzemyslaw Czarnowski const std::string* imageUrlValue = 1229e319cf0SAnna Platash std::get_if<std::string>(&property.second); 123107077deSPrzemyslaw Czarnowski if (imageUrlValue && !imageUrlValue->empty()) 124107077deSPrzemyslaw Czarnowski { 125da4784d8SPrzemyslaw Czarnowski std::filesystem::path filePath = *imageUrlValue; 126da4784d8SPrzemyslaw Czarnowski if (!filePath.has_filename()) 127da4784d8SPrzemyslaw Czarnowski { 1289e319cf0SAnna Platash // this will handle https share, which not 1299e319cf0SAnna Platash // necessarily has to have filename given. 130da4784d8SPrzemyslaw Czarnowski aResp->res.jsonValue["ImageName"] = ""; 131da4784d8SPrzemyslaw Czarnowski } 132da4784d8SPrzemyslaw Czarnowski else 133da4784d8SPrzemyslaw Czarnowski { 1349e319cf0SAnna Platash aResp->res.jsonValue["ImageName"] = 1359e319cf0SAnna Platash filePath.filename(); 136da4784d8SPrzemyslaw Czarnowski } 137da4784d8SPrzemyslaw Czarnowski 138da4784d8SPrzemyslaw Czarnowski aResp->res.jsonValue["Image"] = *imageUrlValue; 139107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Inserted"] = *activeValue; 1409e319cf0SAnna Platash aResp->res.jsonValue["TransferProtocolType"] = 1419e319cf0SAnna Platash getTransferProtocolTypeFromUri(*imageUrlValue); 1429e319cf0SAnna Platash 143107077deSPrzemyslaw Czarnowski if (*activeValue == true) 144107077deSPrzemyslaw Czarnowski { 145107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["ConnectedVia"] = "URI"; 146107077deSPrzemyslaw Czarnowski } 147107077deSPrzemyslaw Czarnowski } 148107077deSPrzemyslaw Czarnowski } 1499e319cf0SAnna Platash else if (property.first == "WriteProtected") 1509e319cf0SAnna Platash { 1519e319cf0SAnna Platash const bool* writeProtectedValue = 1529e319cf0SAnna Platash std::get_if<bool>(&property.second); 1539e319cf0SAnna Platash if (writeProtectedValue) 1549e319cf0SAnna Platash { 1559e319cf0SAnna Platash aResp->res.jsonValue["WriteProtected"] = 1569e319cf0SAnna Platash *writeProtectedValue; 1579e319cf0SAnna Platash } 1589e319cf0SAnna Platash } 1599e319cf0SAnna Platash } 160107077deSPrzemyslaw Czarnowski } 161107077deSPrzemyslaw Czarnowski } 162107077deSPrzemyslaw Czarnowski } 163107077deSPrzemyslaw Czarnowski 164107077deSPrzemyslaw Czarnowski /** 165107077deSPrzemyslaw Czarnowski * @brief Fill template for Virtual Media Item. 166107077deSPrzemyslaw Czarnowski */ 167107077deSPrzemyslaw Czarnowski static nlohmann::json vmItemTemplate(const std::string& name, 168107077deSPrzemyslaw Czarnowski const std::string& resName) 169107077deSPrzemyslaw Czarnowski { 170107077deSPrzemyslaw Czarnowski nlohmann::json item; 171107077deSPrzemyslaw Czarnowski item["@odata.id"] = 172107077deSPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + resName; 173d04ba325SPrzemyslaw Czarnowski item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia"; 174107077deSPrzemyslaw Czarnowski item["Name"] = "Virtual Removable Media"; 175107077deSPrzemyslaw Czarnowski item["Id"] = resName; 176107077deSPrzemyslaw Czarnowski item["WriteProtected"] = true; 177107077deSPrzemyslaw Czarnowski item["MediaTypes"] = {"CD", "USBStick"}; 178107077deSPrzemyslaw Czarnowski item["TransferMethod"] = "Stream"; 179d04ba325SPrzemyslaw Czarnowski item["Oem"]["OpenBMC"]["@odata.type"] = 180d04ba325SPrzemyslaw Czarnowski "#OemVirtualMedia.v1_0_0.VirtualMedia"; 181107077deSPrzemyslaw Czarnowski 182107077deSPrzemyslaw Czarnowski return item; 183107077deSPrzemyslaw Czarnowski } 184107077deSPrzemyslaw Czarnowski 185107077deSPrzemyslaw Czarnowski /** 186107077deSPrzemyslaw Czarnowski * @brief Fills collection data 187107077deSPrzemyslaw Czarnowski */ 1888d1b46d7Szhanghch05 static void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp, 189107077deSPrzemyslaw Czarnowski const std::string& service, 190107077deSPrzemyslaw Czarnowski const std::string& name) 191107077deSPrzemyslaw Czarnowski { 192107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Get available Virtual Media resources."; 193107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 194107077deSPrzemyslaw Czarnowski [name, aResp{std::move(aResp)}](const boost::system::error_code ec, 195107077deSPrzemyslaw Czarnowski ManagedObjectType& subtree) { 196107077deSPrzemyslaw Czarnowski if (ec) 197107077deSPrzemyslaw Czarnowski { 198107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 199107077deSPrzemyslaw Czarnowski return; 200107077deSPrzemyslaw Czarnowski } 201107077deSPrzemyslaw Czarnowski nlohmann::json& members = aResp->res.jsonValue["Members"]; 202107077deSPrzemyslaw Czarnowski members = nlohmann::json::array(); 203107077deSPrzemyslaw Czarnowski 204107077deSPrzemyslaw Czarnowski for (const auto& object : subtree) 205107077deSPrzemyslaw Czarnowski { 206107077deSPrzemyslaw Czarnowski nlohmann::json item; 2072dfd18efSEd Tanous std::string path = object.first.filename(); 2082dfd18efSEd Tanous if (path.empty()) 209107077deSPrzemyslaw Czarnowski { 210107077deSPrzemyslaw Czarnowski continue; 211107077deSPrzemyslaw Czarnowski } 212107077deSPrzemyslaw Czarnowski 2132dfd18efSEd Tanous item["@odata.id"] = 214788ca507SAppaRao Puli "/redfish/v1/Managers/" + name + "/VirtualMedia/" + path; 215107077deSPrzemyslaw Czarnowski 216107077deSPrzemyslaw Czarnowski members.emplace_back(std::move(item)); 217107077deSPrzemyslaw Czarnowski } 218107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Members@odata.count"] = members.size(); 219107077deSPrzemyslaw Czarnowski }, 220107077deSPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 221107077deSPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 222107077deSPrzemyslaw Czarnowski } 223107077deSPrzemyslaw Czarnowski 224107077deSPrzemyslaw Czarnowski /** 225107077deSPrzemyslaw Czarnowski * @brief Fills data for specific resource 226107077deSPrzemyslaw Czarnowski */ 2278d1b46d7Szhanghch05 static void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 228107077deSPrzemyslaw Czarnowski const std::string& service, const std::string& name, 229107077deSPrzemyslaw Czarnowski const std::string& resName) 230107077deSPrzemyslaw Czarnowski { 231107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Get Virtual Media resource data."; 232107077deSPrzemyslaw Czarnowski 233107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 234107077deSPrzemyslaw Czarnowski [resName, name, aResp](const boost::system::error_code ec, 235107077deSPrzemyslaw Czarnowski ManagedObjectType& subtree) { 236107077deSPrzemyslaw Czarnowski if (ec) 237107077deSPrzemyslaw Czarnowski { 238107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 239e13c2760SPrzemyslaw Czarnowski 240107077deSPrzemyslaw Czarnowski return; 241107077deSPrzemyslaw Czarnowski } 242107077deSPrzemyslaw Czarnowski 243107077deSPrzemyslaw Czarnowski for (auto& item : subtree) 244107077deSPrzemyslaw Czarnowski { 2452dfd18efSEd Tanous std::string thispath = item.first.filename(); 2462dfd18efSEd Tanous if (thispath.empty()) 247107077deSPrzemyslaw Czarnowski { 248107077deSPrzemyslaw Czarnowski continue; 249107077deSPrzemyslaw Czarnowski } 250107077deSPrzemyslaw Czarnowski 2512dfd18efSEd Tanous if (thispath != resName) 252107077deSPrzemyslaw Czarnowski { 253107077deSPrzemyslaw Czarnowski continue; 254107077deSPrzemyslaw Czarnowski } 255107077deSPrzemyslaw Czarnowski 256*1a6258dcSPrzemyslaw Czarnowski // "Legacy"/"Proxy" 257*1a6258dcSPrzemyslaw Czarnowski auto mode = item.first.parent_path(); 258*1a6258dcSPrzemyslaw Czarnowski // "VirtualMedia" 259*1a6258dcSPrzemyslaw Czarnowski auto type = mode.parent_path(); 260*1a6258dcSPrzemyslaw Czarnowski if (mode.filename().empty() || type.filename().empty()) 261*1a6258dcSPrzemyslaw Czarnowski { 262*1a6258dcSPrzemyslaw Czarnowski continue; 263*1a6258dcSPrzemyslaw Czarnowski } 264*1a6258dcSPrzemyslaw Czarnowski 265*1a6258dcSPrzemyslaw Czarnowski if (type.filename() != "VirtualMedia") 266*1a6258dcSPrzemyslaw Czarnowski { 267*1a6258dcSPrzemyslaw Czarnowski continue; 268*1a6258dcSPrzemyslaw Czarnowski } 269*1a6258dcSPrzemyslaw Czarnowski 270107077deSPrzemyslaw Czarnowski aResp->res.jsonValue = vmItemTemplate(name, resName); 271107077deSPrzemyslaw Czarnowski 272e13c2760SPrzemyslaw Czarnowski // Check if dbus path is Legacy type 273*1a6258dcSPrzemyslaw Czarnowski if (mode.filename() == "Legacy") 274e13c2760SPrzemyslaw Czarnowski { 275e13c2760SPrzemyslaw Czarnowski aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"] 276e13c2760SPrzemyslaw Czarnowski ["target"] = 277e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + 278e13c2760SPrzemyslaw Czarnowski resName + "/Actions/VirtualMedia.InsertMedia"; 279e13c2760SPrzemyslaw Czarnowski } 280e13c2760SPrzemyslaw Czarnowski 281107077deSPrzemyslaw Czarnowski vmParseInterfaceObject(item.second, aResp); 282107077deSPrzemyslaw Czarnowski 283e13c2760SPrzemyslaw Czarnowski aResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"] 284e13c2760SPrzemyslaw Czarnowski ["target"] = 285e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + 286e13c2760SPrzemyslaw Czarnowski resName + "/Actions/VirtualMedia.EjectMedia"; 287e13c2760SPrzemyslaw Czarnowski 288107077deSPrzemyslaw Czarnowski return; 289107077deSPrzemyslaw Czarnowski } 290107077deSPrzemyslaw Czarnowski 291107077deSPrzemyslaw Czarnowski messages::resourceNotFound( 292d04ba325SPrzemyslaw Czarnowski aResp->res, "#VirtualMedia.v1_3_0.VirtualMedia", resName); 293107077deSPrzemyslaw Czarnowski }, 294107077deSPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 295107077deSPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 296107077deSPrzemyslaw Czarnowski } 297107077deSPrzemyslaw Czarnowski 298e13c2760SPrzemyslaw Czarnowski /** 299e13c2760SPrzemyslaw Czarnowski @brief InsertMedia action class 300e13c2760SPrzemyslaw Czarnowski */ 301e13c2760SPrzemyslaw Czarnowski class VirtualMediaActionInsertMedia : public Node 302e13c2760SPrzemyslaw Czarnowski { 303e13c2760SPrzemyslaw Czarnowski public: 30452cc112dSEd Tanous VirtualMediaActionInsertMedia(App& app) : 305e13c2760SPrzemyslaw Czarnowski Node(app, 306e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/" 307e13c2760SPrzemyslaw Czarnowski "VirtualMedia.InsertMedia", 308e13c2760SPrzemyslaw Czarnowski std::string(), std::string()) 309e13c2760SPrzemyslaw Czarnowski { 310e13c2760SPrzemyslaw Czarnowski entityPrivileges = { 311e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 312e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 313e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 314e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 315e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 316e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 317e13c2760SPrzemyslaw Czarnowski } 318e13c2760SPrzemyslaw Czarnowski 319e13c2760SPrzemyslaw Czarnowski private: 320e13c2760SPrzemyslaw Czarnowski /** 321c6f4e017SAgata Olender * @brief Transfer protocols supported for InsertMedia action. 322c6f4e017SAgata Olender * 323c6f4e017SAgata Olender */ 324c6f4e017SAgata Olender enum class TransferProtocol 325c6f4e017SAgata Olender { 326c6f4e017SAgata Olender https, 327c6f4e017SAgata Olender smb, 328c6f4e017SAgata Olender invalid 329c6f4e017SAgata Olender }; 330c6f4e017SAgata Olender 331c6f4e017SAgata Olender /** 332c6f4e017SAgata Olender * @brief Function extracts transfer protocol type from URI. 333c6f4e017SAgata Olender * 334c6f4e017SAgata Olender */ 335c6f4e017SAgata Olender std::optional<TransferProtocol> 336c6f4e017SAgata Olender getTransferProtocolFromUri(const std::string& imageUri) 337c6f4e017SAgata Olender { 3389e319cf0SAnna Platash try 3399e319cf0SAnna Platash { 3409e319cf0SAnna Platash std::string_view scheme = boost::urls::url_view(imageUri).scheme(); 3419e319cf0SAnna Platash if (scheme == "smb") 342c6f4e017SAgata Olender { 343c6f4e017SAgata Olender return TransferProtocol::smb; 344c6f4e017SAgata Olender } 34581ce609eSEd Tanous if (scheme == "https") 346c6f4e017SAgata Olender { 347c6f4e017SAgata Olender return TransferProtocol::https; 348c6f4e017SAgata Olender } 3499e319cf0SAnna Platash else if (!scheme.empty()) 350c6f4e017SAgata Olender { 351c6f4e017SAgata Olender return TransferProtocol::invalid; 352c6f4e017SAgata Olender } 353c6f4e017SAgata Olender } 3549e319cf0SAnna Platash catch (std::exception& p) 3559e319cf0SAnna Platash { 3569e319cf0SAnna Platash BMCWEB_LOG_ERROR << p.what(); 3579e319cf0SAnna Platash } 3589e319cf0SAnna Platash 3599e319cf0SAnna Platash return {}; 360c6f4e017SAgata Olender } 361c6f4e017SAgata Olender 362c6f4e017SAgata Olender /** 363c6f4e017SAgata Olender * @brief Function convert transfer protocol from string param. 364c6f4e017SAgata Olender * 365c6f4e017SAgata Olender */ 366c6f4e017SAgata Olender std::optional<TransferProtocol> getTransferProtocolFromParam( 367c6f4e017SAgata Olender const std::optional<std::string>& transferProtocolType) 368c6f4e017SAgata Olender { 369c6f4e017SAgata Olender if (transferProtocolType == std::nullopt) 370c6f4e017SAgata Olender { 371c6f4e017SAgata Olender return {}; 372c6f4e017SAgata Olender } 373c6f4e017SAgata Olender 374c6f4e017SAgata Olender if (*transferProtocolType == "CIFS") 375c6f4e017SAgata Olender { 376c6f4e017SAgata Olender return TransferProtocol::smb; 377c6f4e017SAgata Olender } 378c6f4e017SAgata Olender 379c6f4e017SAgata Olender if (*transferProtocolType == "HTTPS") 380c6f4e017SAgata Olender { 381c6f4e017SAgata Olender return TransferProtocol::https; 382c6f4e017SAgata Olender } 383c6f4e017SAgata Olender 384c6f4e017SAgata Olender return TransferProtocol::invalid; 385c6f4e017SAgata Olender } 386c6f4e017SAgata Olender 387c6f4e017SAgata Olender /** 388c6f4e017SAgata Olender * @brief Function extends URI with transfer protocol type. 389c6f4e017SAgata Olender * 390c6f4e017SAgata Olender */ 39181ce609eSEd Tanous std::string 392c6f4e017SAgata Olender getUriWithTransferProtocol(const std::string& imageUri, 393c6f4e017SAgata Olender const TransferProtocol& transferProtocol) 394c6f4e017SAgata Olender { 395c6f4e017SAgata Olender if (transferProtocol == TransferProtocol::smb) 396c6f4e017SAgata Olender { 397c6f4e017SAgata Olender return "smb://" + imageUri; 398c6f4e017SAgata Olender } 399c6f4e017SAgata Olender 400c6f4e017SAgata Olender if (transferProtocol == TransferProtocol::https) 401c6f4e017SAgata Olender { 402c6f4e017SAgata Olender return "https://" + imageUri; 403c6f4e017SAgata Olender } 404c6f4e017SAgata Olender 405c6f4e017SAgata Olender return imageUri; 406c6f4e017SAgata Olender } 407c6f4e017SAgata Olender 408c6f4e017SAgata Olender /** 409c6f4e017SAgata Olender * @brief Function validate parameters of insert media request. 410c6f4e017SAgata Olender * 411c6f4e017SAgata Olender */ 4128d1b46d7Szhanghch05 bool validateParams(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4138d1b46d7Szhanghch05 std::string& imageUrl, 414c6f4e017SAgata Olender const std::optional<bool>& inserted, 415c6f4e017SAgata Olender const std::optional<std::string>& transferMethod, 416c6f4e017SAgata Olender const std::optional<std::string>& transferProtocolType) 417c6f4e017SAgata Olender { 418c6f4e017SAgata Olender BMCWEB_LOG_DEBUG << "Validation started"; 419c6f4e017SAgata Olender // required param imageUrl must not be empty 420c6f4e017SAgata Olender if (imageUrl.empty()) 421c6f4e017SAgata Olender { 422c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter Image is empty."; 423c6f4e017SAgata Olender 4248d1b46d7Szhanghch05 messages::propertyValueFormatError(asyncResp->res, "<empty>", 4258d1b46d7Szhanghch05 "Image"); 426c6f4e017SAgata Olender 427c6f4e017SAgata Olender return false; 428c6f4e017SAgata Olender } 429c6f4e017SAgata Olender 430c6f4e017SAgata Olender // optional param inserted must be true 431c6f4e017SAgata Olender if ((inserted != std::nullopt) && (*inserted != true)) 432c6f4e017SAgata Olender { 433c6f4e017SAgata Olender BMCWEB_LOG_ERROR 434c6f4e017SAgata Olender << "Request action optional parameter Inserted must be true."; 435c6f4e017SAgata Olender 4368d1b46d7Szhanghch05 messages::actionParameterNotSupported(asyncResp->res, "Inserted", 437c6f4e017SAgata Olender "InsertMedia"); 438c6f4e017SAgata Olender 439c6f4e017SAgata Olender return false; 440c6f4e017SAgata Olender } 441c6f4e017SAgata Olender 442c6f4e017SAgata Olender // optional param transferMethod must be stream 443c6f4e017SAgata Olender if ((transferMethod != std::nullopt) && (*transferMethod != "Stream")) 444c6f4e017SAgata Olender { 445c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action optional parameter " 446c6f4e017SAgata Olender "TransferMethod must be Stream."; 447c6f4e017SAgata Olender 4488d1b46d7Szhanghch05 messages::actionParameterNotSupported( 4498d1b46d7Szhanghch05 asyncResp->res, "TransferMethod", "InsertMedia"); 450c6f4e017SAgata Olender 451c6f4e017SAgata Olender return false; 452c6f4e017SAgata Olender } 453c6f4e017SAgata Olender 454c6f4e017SAgata Olender std::optional<TransferProtocol> uriTransferProtocolType = 455c6f4e017SAgata Olender getTransferProtocolFromUri(imageUrl); 456c6f4e017SAgata Olender 457c6f4e017SAgata Olender std::optional<TransferProtocol> paramTransferProtocolType = 458c6f4e017SAgata Olender getTransferProtocolFromParam(transferProtocolType); 459c6f4e017SAgata Olender 460c6f4e017SAgata Olender // ImageUrl does not contain valid protocol type 461c6f4e017SAgata Olender if (*uriTransferProtocolType == TransferProtocol::invalid) 462c6f4e017SAgata Olender { 463c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must " 464c6f4e017SAgata Olender "contain specified protocol type from list: " 465c6f4e017SAgata Olender "(smb, https)."; 466c6f4e017SAgata Olender 4678d1b46d7Szhanghch05 messages::resourceAtUriInUnknownFormat(asyncResp->res, imageUrl); 468c6f4e017SAgata Olender 469c6f4e017SAgata Olender return false; 470c6f4e017SAgata Olender } 471c6f4e017SAgata Olender 472c6f4e017SAgata Olender // transferProtocolType should contain value from list 473c6f4e017SAgata Olender if (*paramTransferProtocolType == TransferProtocol::invalid) 474c6f4e017SAgata Olender { 475c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType " 476c6f4e017SAgata Olender "must be provided with value from list: " 477c6f4e017SAgata Olender "(CIFS, HTTPS)."; 478c6f4e017SAgata Olender 4798d1b46d7Szhanghch05 messages::propertyValueNotInList( 4808d1b46d7Szhanghch05 asyncResp->res, *transferProtocolType, "TransferProtocolType"); 481c6f4e017SAgata Olender return false; 482c6f4e017SAgata Olender } 483c6f4e017SAgata Olender 484c6f4e017SAgata Olender // valid transfer protocol not provided either with URI nor param 485c6f4e017SAgata Olender if ((uriTransferProtocolType == std::nullopt) && 486c6f4e017SAgata Olender (paramTransferProtocolType == std::nullopt)) 487c6f4e017SAgata Olender { 488c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must " 489c6f4e017SAgata Olender "contain specified protocol type or param " 490c6f4e017SAgata Olender "TransferProtocolType must be provided."; 491c6f4e017SAgata Olender 4928d1b46d7Szhanghch05 messages::resourceAtUriInUnknownFormat(asyncResp->res, imageUrl); 493c6f4e017SAgata Olender 494c6f4e017SAgata Olender return false; 495c6f4e017SAgata Olender } 496c6f4e017SAgata Olender 497c6f4e017SAgata Olender // valid transfer protocol provided both with URI and param 498c6f4e017SAgata Olender if ((paramTransferProtocolType != std::nullopt) && 499c6f4e017SAgata Olender (uriTransferProtocolType != std::nullopt)) 500c6f4e017SAgata Olender { 501c6f4e017SAgata Olender // check if protocol is the same for URI and param 502c6f4e017SAgata Olender if (*paramTransferProtocolType != *uriTransferProtocolType) 503c6f4e017SAgata Olender { 504c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter " 505c6f4e017SAgata Olender "TransferProtocolType must contain the " 506c6f4e017SAgata Olender "same protocol type as protocol type " 507c6f4e017SAgata Olender "provided with param imageUrl."; 508c6f4e017SAgata Olender 509c6f4e017SAgata Olender messages::actionParameterValueTypeError( 5108d1b46d7Szhanghch05 asyncResp->res, *transferProtocolType, 5118d1b46d7Szhanghch05 "TransferProtocolType", "InsertMedia"); 512c6f4e017SAgata Olender 513c6f4e017SAgata Olender return false; 514c6f4e017SAgata Olender } 515c6f4e017SAgata Olender } 516c6f4e017SAgata Olender 517c6f4e017SAgata Olender // validation passed 518c6f4e017SAgata Olender // add protocol to URI if needed 519c6f4e017SAgata Olender if (uriTransferProtocolType == std::nullopt) 520c6f4e017SAgata Olender { 521c6f4e017SAgata Olender imageUrl = getUriWithTransferProtocol(imageUrl, 522c6f4e017SAgata Olender *paramTransferProtocolType); 523c6f4e017SAgata Olender } 524c6f4e017SAgata Olender 525c6f4e017SAgata Olender return true; 526c6f4e017SAgata Olender } 527c6f4e017SAgata Olender 528c6f4e017SAgata Olender /** 529e13c2760SPrzemyslaw Czarnowski * @brief Function handles POST method request. 530e13c2760SPrzemyslaw Czarnowski * 531e13c2760SPrzemyslaw Czarnowski * Analyzes POST body message before sends Reset request data to dbus. 532e13c2760SPrzemyslaw Czarnowski */ 5338d1b46d7Szhanghch05 void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5348d1b46d7Szhanghch05 const crow::Request& req, 535e13c2760SPrzemyslaw Czarnowski const std::vector<std::string>& params) override 536e13c2760SPrzemyslaw Czarnowski { 537e13c2760SPrzemyslaw Czarnowski if (params.size() != 2) 538e13c2760SPrzemyslaw Czarnowski { 5398d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 540e13c2760SPrzemyslaw Czarnowski return; 541e13c2760SPrzemyslaw Czarnowski } 542e13c2760SPrzemyslaw Czarnowski 543e13c2760SPrzemyslaw Czarnowski // take resource name from URL 544e13c2760SPrzemyslaw Czarnowski const std::string& resName = params[1]; 545e13c2760SPrzemyslaw Czarnowski 546e13c2760SPrzemyslaw Czarnowski if (params[0] != "bmc") 547e13c2760SPrzemyslaw Czarnowski { 5488d1b46d7Szhanghch05 messages::resourceNotFound(asyncResp->res, "VirtualMedia.Insert", 5498d1b46d7Szhanghch05 resName); 550e13c2760SPrzemyslaw Czarnowski 551e13c2760SPrzemyslaw Czarnowski return; 552e13c2760SPrzemyslaw Czarnowski } 553e13c2760SPrzemyslaw Czarnowski 554e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 5558d1b46d7Szhanghch05 [this, asyncResp, req, 556e13c2760SPrzemyslaw Czarnowski resName](const boost::system::error_code ec, 557e13c2760SPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 558e13c2760SPrzemyslaw Czarnowski if (ec) 559e13c2760SPrzemyslaw Czarnowski { 560e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 561e13c2760SPrzemyslaw Czarnowski << ec; 5628d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 563e13c2760SPrzemyslaw Czarnowski 564e13c2760SPrzemyslaw Czarnowski return; 565e13c2760SPrzemyslaw Czarnowski } 566e13c2760SPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 567e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 568e13c2760SPrzemyslaw Czarnowski 569e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 57081ce609eSEd Tanous [this, service, resName, req, 5718d1b46d7Szhanghch05 asyncResp](const boost::system::error_code ec, 572e13c2760SPrzemyslaw Czarnowski ManagedObjectType& subtree) { 573e13c2760SPrzemyslaw Czarnowski if (ec) 574e13c2760SPrzemyslaw Czarnowski { 575e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 576e13c2760SPrzemyslaw Czarnowski 577e13c2760SPrzemyslaw Czarnowski return; 578e13c2760SPrzemyslaw Czarnowski } 579e13c2760SPrzemyslaw Czarnowski 580e13c2760SPrzemyslaw Czarnowski for (const auto& object : subtree) 581e13c2760SPrzemyslaw Czarnowski { 582e13c2760SPrzemyslaw Czarnowski const std::string& path = 583e13c2760SPrzemyslaw Czarnowski static_cast<const std::string&>(object.first); 584e13c2760SPrzemyslaw Czarnowski 585f23b7296SEd Tanous std::size_t lastIndex = path.rfind('/'); 586e13c2760SPrzemyslaw Czarnowski if (lastIndex == std::string::npos) 587e13c2760SPrzemyslaw Czarnowski { 588e13c2760SPrzemyslaw Czarnowski continue; 589e13c2760SPrzemyslaw Czarnowski } 590e13c2760SPrzemyslaw Czarnowski 591e13c2760SPrzemyslaw Czarnowski lastIndex += 1; 592e13c2760SPrzemyslaw Czarnowski 593e13c2760SPrzemyslaw Czarnowski if (path.substr(lastIndex) == resName) 594e13c2760SPrzemyslaw Czarnowski { 595e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Proxy"); 596e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 597e13c2760SPrzemyslaw Czarnowski { 598e13c2760SPrzemyslaw Czarnowski // Not possible in proxy mode 599e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "InsertMedia not " 600e13c2760SPrzemyslaw Czarnowski "allowed in proxy mode"; 601e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound( 6028d1b46d7Szhanghch05 asyncResp->res, 6038d1b46d7Szhanghch05 "VirtualMedia.InsertMedia", resName); 604e13c2760SPrzemyslaw Czarnowski 605e13c2760SPrzemyslaw Czarnowski return; 606e13c2760SPrzemyslaw Czarnowski } 607e13c2760SPrzemyslaw Czarnowski 608e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Legacy"); 609c6f4e017SAgata Olender if (lastIndex == std::string::npos) 610e13c2760SPrzemyslaw Czarnowski { 611c6f4e017SAgata Olender continue; 612c6f4e017SAgata Olender } 613c6f4e017SAgata Olender 614e13c2760SPrzemyslaw Czarnowski // Legacy mode 615e13c2760SPrzemyslaw Czarnowski std::string imageUrl; 616c6f4e017SAgata Olender std::optional<std::string> userName; 617c6f4e017SAgata Olender std::optional<std::string> password; 618c6f4e017SAgata Olender std::optional<std::string> transferMethod; 619c6f4e017SAgata Olender std::optional<std::string> transferProtocolType; 620c6f4e017SAgata Olender std::optional<bool> writeProtected = true; 621c6f4e017SAgata Olender std::optional<bool> inserted; 622e13c2760SPrzemyslaw Czarnowski 6234e0453b1SGunnar Mills // Read obligatory parameters (url of image) 624d6da5bebSAdrian Ambrożewicz if (!json_util::readJson( 6258d1b46d7Szhanghch05 req, asyncResp->res, "Image", imageUrl, 626988fb7b2SAdrian Ambrożewicz "WriteProtected", writeProtected, 627988fb7b2SAdrian Ambrożewicz "UserName", userName, "Password", 628c6f4e017SAgata Olender password, "Inserted", inserted, 629c6f4e017SAgata Olender "TransferMethod", transferMethod, 630c6f4e017SAgata Olender "TransferProtocolType", 631c6f4e017SAgata Olender transferProtocolType)) 632e13c2760SPrzemyslaw Czarnowski { 633c6f4e017SAgata Olender BMCWEB_LOG_DEBUG << "Image is not provided"; 634e13c2760SPrzemyslaw Czarnowski return; 635e13c2760SPrzemyslaw Czarnowski } 636e13c2760SPrzemyslaw Czarnowski 637c6f4e017SAgata Olender bool paramsValid = validateParams( 6388d1b46d7Szhanghch05 asyncResp->res, imageUrl, inserted, 639c6f4e017SAgata Olender transferMethod, transferProtocolType); 640c6f4e017SAgata Olender 641c6f4e017SAgata Olender if (paramsValid == false) 642e13c2760SPrzemyslaw Czarnowski { 643e13c2760SPrzemyslaw Czarnowski return; 644e13c2760SPrzemyslaw Czarnowski } 645e13c2760SPrzemyslaw Czarnowski 646c6f4e017SAgata Olender // manager is irrelevant for VirtualMedia dbus 647c6f4e017SAgata Olender // calls 6488d1b46d7Szhanghch05 doMountVmLegacy(asyncResp, service, resName, 649c6f4e017SAgata Olender imageUrl, !(*writeProtected), 65081ce609eSEd Tanous std::move(*userName), 65181ce609eSEd Tanous std::move(*password)); 652e13c2760SPrzemyslaw Czarnowski 653e13c2760SPrzemyslaw Czarnowski return; 654e13c2760SPrzemyslaw Czarnowski } 655e13c2760SPrzemyslaw Czarnowski } 656e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Parent item not found"; 6578d1b46d7Szhanghch05 messages::resourceNotFound(asyncResp->res, 6588d1b46d7Szhanghch05 "VirtualMedia", resName); 659e13c2760SPrzemyslaw Czarnowski }, 660e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 661e13c2760SPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 662e13c2760SPrzemyslaw Czarnowski }, 663e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 664e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 665e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 666e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 667e13c2760SPrzemyslaw Czarnowski } 668e13c2760SPrzemyslaw Czarnowski 6691214b7e7SGunnar Mills template <typename T> 6701214b7e7SGunnar Mills static void secureCleanup(T& value) 671988fb7b2SAdrian Ambrożewicz { 672988fb7b2SAdrian Ambrożewicz auto raw = const_cast<typename T::value_type*>(value.data()); 673988fb7b2SAdrian Ambrożewicz explicit_bzero(raw, value.size() * sizeof(*raw)); 674988fb7b2SAdrian Ambrożewicz } 675988fb7b2SAdrian Ambrożewicz 676988fb7b2SAdrian Ambrożewicz class Credentials 677988fb7b2SAdrian Ambrożewicz { 678988fb7b2SAdrian Ambrożewicz public: 679988fb7b2SAdrian Ambrożewicz Credentials(std::string&& user, std::string&& password) : 680988fb7b2SAdrian Ambrożewicz userBuf(std::move(user)), passBuf(std::move(password)) 6811214b7e7SGunnar Mills {} 682988fb7b2SAdrian Ambrożewicz 683988fb7b2SAdrian Ambrożewicz ~Credentials() 684988fb7b2SAdrian Ambrożewicz { 685988fb7b2SAdrian Ambrożewicz secureCleanup(userBuf); 686988fb7b2SAdrian Ambrożewicz secureCleanup(passBuf); 687988fb7b2SAdrian Ambrożewicz } 688988fb7b2SAdrian Ambrożewicz 689988fb7b2SAdrian Ambrożewicz const std::string& user() 690988fb7b2SAdrian Ambrożewicz { 691988fb7b2SAdrian Ambrożewicz return userBuf; 692988fb7b2SAdrian Ambrożewicz } 693988fb7b2SAdrian Ambrożewicz 694988fb7b2SAdrian Ambrożewicz const std::string& password() 695988fb7b2SAdrian Ambrożewicz { 696988fb7b2SAdrian Ambrożewicz return passBuf; 697988fb7b2SAdrian Ambrożewicz } 698988fb7b2SAdrian Ambrożewicz 699988fb7b2SAdrian Ambrożewicz private: 700988fb7b2SAdrian Ambrożewicz Credentials() = delete; 701988fb7b2SAdrian Ambrożewicz Credentials(const Credentials&) = delete; 702988fb7b2SAdrian Ambrożewicz Credentials& operator=(const Credentials&) = delete; 703988fb7b2SAdrian Ambrożewicz 704988fb7b2SAdrian Ambrożewicz std::string userBuf; 705988fb7b2SAdrian Ambrożewicz std::string passBuf; 706988fb7b2SAdrian Ambrożewicz }; 707988fb7b2SAdrian Ambrożewicz 708988fb7b2SAdrian Ambrożewicz class CredentialsProvider 709988fb7b2SAdrian Ambrożewicz { 710988fb7b2SAdrian Ambrożewicz public: 7111214b7e7SGunnar Mills template <typename T> 7121214b7e7SGunnar Mills struct Deleter 713988fb7b2SAdrian Ambrożewicz { 714988fb7b2SAdrian Ambrożewicz void operator()(T* buff) const 715988fb7b2SAdrian Ambrożewicz { 716988fb7b2SAdrian Ambrożewicz if (buff) 717988fb7b2SAdrian Ambrożewicz { 718988fb7b2SAdrian Ambrożewicz secureCleanup(*buff); 719988fb7b2SAdrian Ambrożewicz delete buff; 720988fb7b2SAdrian Ambrożewicz } 721988fb7b2SAdrian Ambrożewicz } 722988fb7b2SAdrian Ambrożewicz }; 723988fb7b2SAdrian Ambrożewicz 724988fb7b2SAdrian Ambrożewicz using Buffer = std::vector<char>; 725988fb7b2SAdrian Ambrożewicz using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>; 726988fb7b2SAdrian Ambrożewicz // Using explicit definition instead of std::function to avoid implicit 727988fb7b2SAdrian Ambrożewicz // conversions eg. stack copy instead of reference 728988fb7b2SAdrian Ambrożewicz using FormatterFunc = void(const std::string& username, 729988fb7b2SAdrian Ambrożewicz const std::string& password, Buffer& dest); 730988fb7b2SAdrian Ambrożewicz 731988fb7b2SAdrian Ambrożewicz CredentialsProvider(std::string&& user, std::string&& password) : 732988fb7b2SAdrian Ambrożewicz credentials(std::move(user), std::move(password)) 7331214b7e7SGunnar Mills {} 734988fb7b2SAdrian Ambrożewicz 735988fb7b2SAdrian Ambrożewicz const std::string& user() 736988fb7b2SAdrian Ambrożewicz { 737988fb7b2SAdrian Ambrożewicz return credentials.user(); 738988fb7b2SAdrian Ambrożewicz } 739988fb7b2SAdrian Ambrożewicz 740988fb7b2SAdrian Ambrożewicz const std::string& password() 741988fb7b2SAdrian Ambrożewicz { 742988fb7b2SAdrian Ambrożewicz return credentials.password(); 743988fb7b2SAdrian Ambrożewicz } 744988fb7b2SAdrian Ambrożewicz 74581ce609eSEd Tanous SecureBuffer pack(FormatterFunc formatter) 746988fb7b2SAdrian Ambrożewicz { 747988fb7b2SAdrian Ambrożewicz SecureBuffer packed{new Buffer{}}; 748988fb7b2SAdrian Ambrożewicz if (formatter) 749988fb7b2SAdrian Ambrożewicz { 750988fb7b2SAdrian Ambrożewicz formatter(credentials.user(), credentials.password(), *packed); 751988fb7b2SAdrian Ambrożewicz } 752988fb7b2SAdrian Ambrożewicz 753988fb7b2SAdrian Ambrożewicz return packed; 754988fb7b2SAdrian Ambrożewicz } 755988fb7b2SAdrian Ambrożewicz 756988fb7b2SAdrian Ambrożewicz private: 757988fb7b2SAdrian Ambrożewicz Credentials credentials; 758988fb7b2SAdrian Ambrożewicz }; 759988fb7b2SAdrian Ambrożewicz 760988fb7b2SAdrian Ambrożewicz // Wrapper for boost::async_pipe ensuring proper pipe cleanup 7611214b7e7SGunnar Mills template <typename Buffer> 7621214b7e7SGunnar Mills class Pipe 763988fb7b2SAdrian Ambrożewicz { 764988fb7b2SAdrian Ambrożewicz public: 765988fb7b2SAdrian Ambrożewicz using unix_fd = sdbusplus::message::unix_fd; 766988fb7b2SAdrian Ambrożewicz 767988fb7b2SAdrian Ambrożewicz Pipe(boost::asio::io_context& io, Buffer&& buffer) : 768988fb7b2SAdrian Ambrożewicz impl(io), buffer{std::move(buffer)} 7691214b7e7SGunnar Mills {} 770988fb7b2SAdrian Ambrożewicz 771988fb7b2SAdrian Ambrożewicz ~Pipe() 772988fb7b2SAdrian Ambrożewicz { 773988fb7b2SAdrian Ambrożewicz // Named pipe needs to be explicitly removed 774988fb7b2SAdrian Ambrożewicz impl.close(); 775988fb7b2SAdrian Ambrożewicz } 776988fb7b2SAdrian Ambrożewicz 777988fb7b2SAdrian Ambrożewicz unix_fd fd() 778988fb7b2SAdrian Ambrożewicz { 779988fb7b2SAdrian Ambrożewicz return unix_fd{impl.native_source()}; 780988fb7b2SAdrian Ambrożewicz } 781988fb7b2SAdrian Ambrożewicz 782988fb7b2SAdrian Ambrożewicz template <typename WriteHandler> 78381ce609eSEd Tanous void asyncWrite(WriteHandler&& handler) 784988fb7b2SAdrian Ambrożewicz { 785988fb7b2SAdrian Ambrożewicz impl.async_write_some(data(), std::forward<WriteHandler>(handler)); 786988fb7b2SAdrian Ambrożewicz } 787988fb7b2SAdrian Ambrożewicz 788988fb7b2SAdrian Ambrożewicz private: 789988fb7b2SAdrian Ambrożewicz // Specialization for pointer types 790988fb7b2SAdrian Ambrożewicz template <typename B = Buffer> 791988fb7b2SAdrian Ambrożewicz typename std::enable_if<boost::has_dereference<B>::value, 792988fb7b2SAdrian Ambrożewicz boost::asio::const_buffer>::type 793988fb7b2SAdrian Ambrożewicz data() 794988fb7b2SAdrian Ambrożewicz { 795988fb7b2SAdrian Ambrożewicz return boost::asio::buffer(*buffer); 796988fb7b2SAdrian Ambrożewicz } 797988fb7b2SAdrian Ambrożewicz 798988fb7b2SAdrian Ambrożewicz template <typename B = Buffer> 799988fb7b2SAdrian Ambrożewicz typename std::enable_if<!boost::has_dereference<B>::value, 800988fb7b2SAdrian Ambrożewicz boost::asio::const_buffer>::type 801988fb7b2SAdrian Ambrożewicz data() 802988fb7b2SAdrian Ambrożewicz { 803988fb7b2SAdrian Ambrożewicz return boost::asio::buffer(buffer); 804988fb7b2SAdrian Ambrożewicz } 805988fb7b2SAdrian Ambrożewicz 806988fb7b2SAdrian Ambrożewicz const std::string name; 807988fb7b2SAdrian Ambrożewicz boost::process::async_pipe impl; 808988fb7b2SAdrian Ambrożewicz Buffer buffer; 809988fb7b2SAdrian Ambrożewicz }; 810988fb7b2SAdrian Ambrożewicz 811e13c2760SPrzemyslaw Czarnowski /** 812e13c2760SPrzemyslaw Czarnowski * @brief Function transceives data with dbus directly. 813e13c2760SPrzemyslaw Czarnowski * 814e13c2760SPrzemyslaw Czarnowski * All BMC state properties will be retrieved before sending reset request. 815e13c2760SPrzemyslaw Czarnowski */ 8168d1b46d7Szhanghch05 void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 817e13c2760SPrzemyslaw Czarnowski const std::string& service, const std::string& name, 818988fb7b2SAdrian Ambrożewicz const std::string& imageUrl, const bool rw, 819988fb7b2SAdrian Ambrożewicz std::string&& userName, std::string&& password) 820e13c2760SPrzemyslaw Czarnowski { 821988fb7b2SAdrian Ambrożewicz using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>; 822988fb7b2SAdrian Ambrożewicz constexpr const size_t secretLimit = 1024; 823988fb7b2SAdrian Ambrożewicz 824988fb7b2SAdrian Ambrożewicz std::shared_ptr<SecurePipe> secretPipe; 825988fb7b2SAdrian Ambrożewicz std::variant<int, SecurePipe::unix_fd> unixFd = -1; 826988fb7b2SAdrian Ambrożewicz 827988fb7b2SAdrian Ambrożewicz if (!userName.empty() || !password.empty()) 828988fb7b2SAdrian Ambrożewicz { 829988fb7b2SAdrian Ambrożewicz // Encapsulate in safe buffer 830988fb7b2SAdrian Ambrożewicz CredentialsProvider credentials(std::move(userName), 831988fb7b2SAdrian Ambrożewicz std::move(password)); 832988fb7b2SAdrian Ambrożewicz 833988fb7b2SAdrian Ambrożewicz // Payload must contain data + NULL delimiters 834988fb7b2SAdrian Ambrożewicz if (credentials.user().size() + credentials.password().size() + 2 > 835988fb7b2SAdrian Ambrożewicz secretLimit) 836988fb7b2SAdrian Ambrożewicz { 837988fb7b2SAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Credentials too long to handle"; 838988fb7b2SAdrian Ambrożewicz messages::unrecognizedRequestBody(asyncResp->res); 839988fb7b2SAdrian Ambrożewicz return; 840988fb7b2SAdrian Ambrożewicz } 841988fb7b2SAdrian Ambrożewicz 842988fb7b2SAdrian Ambrożewicz // Pack secret 843988fb7b2SAdrian Ambrożewicz auto secret = credentials.pack([](const auto& user, 844988fb7b2SAdrian Ambrożewicz const auto& pass, auto& buff) { 845988fb7b2SAdrian Ambrożewicz std::copy(user.begin(), user.end(), std::back_inserter(buff)); 846988fb7b2SAdrian Ambrożewicz buff.push_back('\0'); 847988fb7b2SAdrian Ambrożewicz std::copy(pass.begin(), pass.end(), std::back_inserter(buff)); 848988fb7b2SAdrian Ambrożewicz buff.push_back('\0'); 849988fb7b2SAdrian Ambrożewicz }); 850988fb7b2SAdrian Ambrożewicz 851988fb7b2SAdrian Ambrożewicz // Open pipe 852988fb7b2SAdrian Ambrożewicz secretPipe = std::make_shared<SecurePipe>( 853988fb7b2SAdrian Ambrożewicz crow::connections::systemBus->get_io_context(), 854988fb7b2SAdrian Ambrożewicz std::move(secret)); 855988fb7b2SAdrian Ambrożewicz unixFd = secretPipe->fd(); 856988fb7b2SAdrian Ambrożewicz 857988fb7b2SAdrian Ambrożewicz // Pass secret over pipe 85881ce609eSEd Tanous secretPipe->asyncWrite( 859f5b16f03SVikram Bodireddy [asyncResp](const boost::system::error_code& ec, std::size_t) { 860988fb7b2SAdrian Ambrożewicz if (ec) 861988fb7b2SAdrian Ambrożewicz { 862988fb7b2SAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec; 863988fb7b2SAdrian Ambrożewicz messages::internalError(asyncResp->res); 864988fb7b2SAdrian Ambrożewicz } 865988fb7b2SAdrian Ambrożewicz }); 866988fb7b2SAdrian Ambrożewicz } 867988fb7b2SAdrian Ambrożewicz 868e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 869988fb7b2SAdrian Ambrożewicz [asyncResp, secretPipe](const boost::system::error_code ec, 870988fb7b2SAdrian Ambrożewicz bool success) { 871e13c2760SPrzemyslaw Czarnowski if (ec) 872e13c2760SPrzemyslaw Czarnowski { 873e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 874e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 875d6da5bebSAdrian Ambrożewicz } 876d6da5bebSAdrian Ambrożewicz else if (!success) 877d6da5bebSAdrian Ambrożewicz { 878d6da5bebSAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Service responded with error"; 879d6da5bebSAdrian Ambrożewicz messages::generalError(asyncResp->res); 880e13c2760SPrzemyslaw Czarnowski } 881e13c2760SPrzemyslaw Czarnowski }, 882e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, 883988fb7b2SAdrian Ambrożewicz "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw, 884988fb7b2SAdrian Ambrożewicz unixFd); 885e13c2760SPrzemyslaw Czarnowski } 886e13c2760SPrzemyslaw Czarnowski }; 887e13c2760SPrzemyslaw Czarnowski 888e13c2760SPrzemyslaw Czarnowski /** 889e13c2760SPrzemyslaw Czarnowski @brief EjectMedia action class 890e13c2760SPrzemyslaw Czarnowski */ 891e13c2760SPrzemyslaw Czarnowski class VirtualMediaActionEjectMedia : public Node 892e13c2760SPrzemyslaw Czarnowski { 893e13c2760SPrzemyslaw Czarnowski public: 89452cc112dSEd Tanous VirtualMediaActionEjectMedia(App& app) : 895e13c2760SPrzemyslaw Czarnowski Node(app, 896e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/" 897e13c2760SPrzemyslaw Czarnowski "VirtualMedia.EjectMedia", 898e13c2760SPrzemyslaw Czarnowski std::string(), std::string()) 899e13c2760SPrzemyslaw Czarnowski { 900e13c2760SPrzemyslaw Czarnowski entityPrivileges = { 901e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 902e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 903e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 904e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 905e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 906e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 907e13c2760SPrzemyslaw Czarnowski } 908e13c2760SPrzemyslaw Czarnowski 909e13c2760SPrzemyslaw Czarnowski private: 910e13c2760SPrzemyslaw Czarnowski /** 911e13c2760SPrzemyslaw Czarnowski * @brief Function handles POST method request. 912e13c2760SPrzemyslaw Czarnowski * 913e13c2760SPrzemyslaw Czarnowski * Analyzes POST body message before sends Reset request data to dbus. 914e13c2760SPrzemyslaw Czarnowski */ 9158d1b46d7Szhanghch05 void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9168d1b46d7Szhanghch05 const crow::Request& req, 917e13c2760SPrzemyslaw Czarnowski const std::vector<std::string>& params) override 918e13c2760SPrzemyslaw Czarnowski { 919e13c2760SPrzemyslaw Czarnowski if (params.size() != 2) 920e13c2760SPrzemyslaw Czarnowski { 9218d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 922e13c2760SPrzemyslaw Czarnowski return; 923e13c2760SPrzemyslaw Czarnowski } 924e13c2760SPrzemyslaw Czarnowski 925e13c2760SPrzemyslaw Czarnowski // take resource name from URL 926e13c2760SPrzemyslaw Czarnowski const std::string& resName = params[1]; 927e13c2760SPrzemyslaw Czarnowski 928e13c2760SPrzemyslaw Czarnowski if (params[0] != "bmc") 929e13c2760SPrzemyslaw Czarnowski { 9308d1b46d7Szhanghch05 messages::resourceNotFound(asyncResp->res, "VirtualMedia.Eject", 9318d1b46d7Szhanghch05 resName); 932e13c2760SPrzemyslaw Czarnowski 933e13c2760SPrzemyslaw Czarnowski return; 934e13c2760SPrzemyslaw Czarnowski } 935e13c2760SPrzemyslaw Czarnowski 936e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 9378d1b46d7Szhanghch05 [this, asyncResp{std::move(asyncResp)}, req, 938e13c2760SPrzemyslaw Czarnowski resName](const boost::system::error_code ec, 939e13c2760SPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 940e13c2760SPrzemyslaw Czarnowski if (ec) 941e13c2760SPrzemyslaw Czarnowski { 942e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 943e13c2760SPrzemyslaw Czarnowski << ec; 9448d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 945e13c2760SPrzemyslaw Czarnowski 946e13c2760SPrzemyslaw Czarnowski return; 947e13c2760SPrzemyslaw Czarnowski } 948e13c2760SPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 949e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 950e13c2760SPrzemyslaw Czarnowski 951e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 95281ce609eSEd Tanous [this, resName, service, req, 9538d1b46d7Szhanghch05 asyncResp{asyncResp}](const boost::system::error_code ec, 954e13c2760SPrzemyslaw Czarnowski ManagedObjectType& subtree) { 955e13c2760SPrzemyslaw Czarnowski if (ec) 956e13c2760SPrzemyslaw Czarnowski { 957e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 958e13c2760SPrzemyslaw Czarnowski 959e13c2760SPrzemyslaw Czarnowski return; 960e13c2760SPrzemyslaw Czarnowski } 961e13c2760SPrzemyslaw Czarnowski 962e13c2760SPrzemyslaw Czarnowski for (const auto& object : subtree) 963e13c2760SPrzemyslaw Czarnowski { 964e13c2760SPrzemyslaw Czarnowski const std::string& path = 965e13c2760SPrzemyslaw Czarnowski static_cast<const std::string&>(object.first); 966e13c2760SPrzemyslaw Czarnowski 967f23b7296SEd Tanous std::size_t lastIndex = path.rfind('/'); 968e13c2760SPrzemyslaw Czarnowski if (lastIndex == std::string::npos) 969e13c2760SPrzemyslaw Czarnowski { 970e13c2760SPrzemyslaw Czarnowski continue; 971e13c2760SPrzemyslaw Czarnowski } 972e13c2760SPrzemyslaw Czarnowski 973e13c2760SPrzemyslaw Czarnowski lastIndex += 1; 974e13c2760SPrzemyslaw Czarnowski 975e13c2760SPrzemyslaw Czarnowski if (path.substr(lastIndex) == resName) 976e13c2760SPrzemyslaw Czarnowski { 977e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Proxy"); 978e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 979e13c2760SPrzemyslaw Czarnowski { 980e13c2760SPrzemyslaw Czarnowski // Proxy mode 9818d1b46d7Szhanghch05 doVmAction(asyncResp, service, resName, 9828d1b46d7Szhanghch05 false); 983e13c2760SPrzemyslaw Czarnowski } 984e13c2760SPrzemyslaw Czarnowski 985e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Legacy"); 986e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 987e13c2760SPrzemyslaw Czarnowski { 988e13c2760SPrzemyslaw Czarnowski // Legacy mode 9898d1b46d7Szhanghch05 doVmAction(asyncResp, service, resName, 9908d1b46d7Szhanghch05 true); 991e13c2760SPrzemyslaw Czarnowski } 992e13c2760SPrzemyslaw Czarnowski 993e13c2760SPrzemyslaw Czarnowski return; 994e13c2760SPrzemyslaw Czarnowski } 995e13c2760SPrzemyslaw Czarnowski } 996e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Parent item not found"; 9978d1b46d7Szhanghch05 messages::resourceNotFound(asyncResp->res, 9988d1b46d7Szhanghch05 "VirtualMedia", resName); 999e13c2760SPrzemyslaw Czarnowski }, 1000e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 1001e13c2760SPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 1002e13c2760SPrzemyslaw Czarnowski }, 1003e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 1004e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 1005e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 1006e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 1007e13c2760SPrzemyslaw Czarnowski } 1008e13c2760SPrzemyslaw Czarnowski 1009e13c2760SPrzemyslaw Czarnowski /** 1010e13c2760SPrzemyslaw Czarnowski * @brief Function transceives data with dbus directly. 1011e13c2760SPrzemyslaw Czarnowski * 1012e13c2760SPrzemyslaw Czarnowski * All BMC state properties will be retrieved before sending reset request. 1013e13c2760SPrzemyslaw Czarnowski */ 10148d1b46d7Szhanghch05 void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1015e13c2760SPrzemyslaw Czarnowski const std::string& service, const std::string& name, 1016e13c2760SPrzemyslaw Czarnowski bool legacy) 1017e13c2760SPrzemyslaw Czarnowski { 1018e13c2760SPrzemyslaw Czarnowski 1019e13c2760SPrzemyslaw Czarnowski // Legacy mount requires parameter with image 1020e13c2760SPrzemyslaw Czarnowski if (legacy) 1021e13c2760SPrzemyslaw Czarnowski { 1022e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1023e13c2760SPrzemyslaw Czarnowski [asyncResp](const boost::system::error_code ec) { 1024e13c2760SPrzemyslaw Czarnowski if (ec) 1025e13c2760SPrzemyslaw Czarnowski { 1026e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 1027e13c2760SPrzemyslaw Czarnowski 1028e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1029e13c2760SPrzemyslaw Czarnowski return; 1030e13c2760SPrzemyslaw Czarnowski } 1031e13c2760SPrzemyslaw Czarnowski }, 1032e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, 1033e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount"); 1034e13c2760SPrzemyslaw Czarnowski } 1035e13c2760SPrzemyslaw Czarnowski else // proxy 1036e13c2760SPrzemyslaw Czarnowski { 1037e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1038e13c2760SPrzemyslaw Czarnowski [asyncResp](const boost::system::error_code ec) { 1039e13c2760SPrzemyslaw Czarnowski if (ec) 1040e13c2760SPrzemyslaw Czarnowski { 1041e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 1042e13c2760SPrzemyslaw Czarnowski 1043e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1044e13c2760SPrzemyslaw Czarnowski return; 1045e13c2760SPrzemyslaw Czarnowski } 1046e13c2760SPrzemyslaw Czarnowski }, 1047e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name, 1048e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount"); 1049e13c2760SPrzemyslaw Czarnowski } 1050e13c2760SPrzemyslaw Czarnowski } 1051e13c2760SPrzemyslaw Czarnowski }; 1052e13c2760SPrzemyslaw Czarnowski 1053107077deSPrzemyslaw Czarnowski class VirtualMediaCollection : public Node 1054107077deSPrzemyslaw Czarnowski { 1055107077deSPrzemyslaw Czarnowski public: 1056107077deSPrzemyslaw Czarnowski /* 1057107077deSPrzemyslaw Czarnowski * Default Constructor 1058107077deSPrzemyslaw Czarnowski */ 105952cc112dSEd Tanous VirtualMediaCollection(App& app) : 1060107077deSPrzemyslaw Czarnowski Node(app, "/redfish/v1/Managers/<str>/VirtualMedia/", std::string()) 1061107077deSPrzemyslaw Czarnowski { 1062107077deSPrzemyslaw Czarnowski entityPrivileges = { 1063107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 1064107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 1065107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 1066107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 1067107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 1068107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 1069107077deSPrzemyslaw Czarnowski } 1070107077deSPrzemyslaw Czarnowski 1071107077deSPrzemyslaw Czarnowski private: 1072107077deSPrzemyslaw Czarnowski /** 1073107077deSPrzemyslaw Czarnowski * Functions triggers appropriate requests on DBus 1074107077deSPrzemyslaw Czarnowski */ 10758d1b46d7Szhanghch05 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10768d1b46d7Szhanghch05 const crow::Request&, 1077107077deSPrzemyslaw Czarnowski const std::vector<std::string>& params) override 1078107077deSPrzemyslaw Czarnowski { 1079107077deSPrzemyslaw Czarnowski 1080107077deSPrzemyslaw Czarnowski // Check if there is required param, truly entering this shall be 1081107077deSPrzemyslaw Czarnowski // impossible 1082107077deSPrzemyslaw Czarnowski if (params.size() != 1) 1083107077deSPrzemyslaw Czarnowski { 10848d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 1085107077deSPrzemyslaw Czarnowski 1086107077deSPrzemyslaw Czarnowski return; 1087107077deSPrzemyslaw Czarnowski } 1088107077deSPrzemyslaw Czarnowski 1089107077deSPrzemyslaw Czarnowski const std::string& name = params[0]; 1090107077deSPrzemyslaw Czarnowski 1091107077deSPrzemyslaw Czarnowski if (name != "bmc") 1092107077deSPrzemyslaw Czarnowski { 1093107077deSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, "VirtualMedia", name); 1094107077deSPrzemyslaw Czarnowski 1095107077deSPrzemyslaw Czarnowski return; 1096107077deSPrzemyslaw Czarnowski } 1097107077deSPrzemyslaw Czarnowski 10988d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1099107077deSPrzemyslaw Czarnowski "#VirtualMediaCollection.VirtualMediaCollection"; 11008d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Virtual Media Services"; 11018d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 1102d6c414f3SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia"; 1103107077deSPrzemyslaw Czarnowski 1104107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1105107077deSPrzemyslaw Czarnowski [asyncResp, name](const boost::system::error_code ec, 1106107077deSPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 1107107077deSPrzemyslaw Czarnowski if (ec) 1108107077deSPrzemyslaw Czarnowski { 1109107077deSPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 1110107077deSPrzemyslaw Czarnowski << ec; 1111107077deSPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1112107077deSPrzemyslaw Czarnowski 1113107077deSPrzemyslaw Czarnowski return; 1114107077deSPrzemyslaw Czarnowski } 1115107077deSPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 1116107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 1117107077deSPrzemyslaw Czarnowski 1118107077deSPrzemyslaw Czarnowski getVmResourceList(asyncResp, service, name); 1119107077deSPrzemyslaw Czarnowski }, 1120107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 1121107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 1122107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 1123107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 1124107077deSPrzemyslaw Czarnowski } 1125107077deSPrzemyslaw Czarnowski }; 1126107077deSPrzemyslaw Czarnowski 1127107077deSPrzemyslaw Czarnowski class VirtualMedia : public Node 1128107077deSPrzemyslaw Czarnowski { 1129107077deSPrzemyslaw Czarnowski public: 1130107077deSPrzemyslaw Czarnowski /* 1131107077deSPrzemyslaw Czarnowski * Default Constructor 1132107077deSPrzemyslaw Czarnowski */ 113352cc112dSEd Tanous VirtualMedia(App& app) : 1134107077deSPrzemyslaw Czarnowski Node(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/", 1135107077deSPrzemyslaw Czarnowski std::string(), std::string()) 1136107077deSPrzemyslaw Czarnowski { 1137107077deSPrzemyslaw Czarnowski entityPrivileges = { 1138107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 1139107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 1140107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 1141107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 1142107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 1143107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 1144107077deSPrzemyslaw Czarnowski } 1145107077deSPrzemyslaw Czarnowski 1146107077deSPrzemyslaw Czarnowski private: 1147107077deSPrzemyslaw Czarnowski /** 1148107077deSPrzemyslaw Czarnowski * Functions triggers appropriate requests on DBus 1149107077deSPrzemyslaw Czarnowski */ 11508d1b46d7Szhanghch05 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11518d1b46d7Szhanghch05 const crow::Request&, 1152107077deSPrzemyslaw Czarnowski const std::vector<std::string>& params) override 1153107077deSPrzemyslaw Czarnowski { 1154107077deSPrzemyslaw Czarnowski // Check if there is required param, truly entering this shall be 1155107077deSPrzemyslaw Czarnowski // impossible 1156107077deSPrzemyslaw Czarnowski if (params.size() != 2) 1157107077deSPrzemyslaw Czarnowski { 11588d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 1159107077deSPrzemyslaw Czarnowski return; 1160107077deSPrzemyslaw Czarnowski } 1161107077deSPrzemyslaw Czarnowski const std::string& name = params[0]; 1162107077deSPrzemyslaw Czarnowski const std::string& resName = params[1]; 1163107077deSPrzemyslaw Czarnowski 1164107077deSPrzemyslaw Czarnowski if (name != "bmc") 1165107077deSPrzemyslaw Czarnowski { 1166107077deSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName); 1167107077deSPrzemyslaw Czarnowski 1168107077deSPrzemyslaw Czarnowski return; 1169107077deSPrzemyslaw Czarnowski } 1170107077deSPrzemyslaw Czarnowski 1171107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1172107077deSPrzemyslaw Czarnowski [asyncResp, name, resName](const boost::system::error_code ec, 1173107077deSPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 1174107077deSPrzemyslaw Czarnowski if (ec) 1175107077deSPrzemyslaw Czarnowski { 1176107077deSPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 1177107077deSPrzemyslaw Czarnowski << ec; 1178107077deSPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1179107077deSPrzemyslaw Czarnowski 1180107077deSPrzemyslaw Czarnowski return; 1181107077deSPrzemyslaw Czarnowski } 1182107077deSPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 1183107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 1184107077deSPrzemyslaw Czarnowski 1185107077deSPrzemyslaw Czarnowski getVmData(asyncResp, service, name, resName); 1186107077deSPrzemyslaw Czarnowski }, 1187107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 1188107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 1189107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 1190107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 1191107077deSPrzemyslaw Czarnowski } 1192107077deSPrzemyslaw Czarnowski }; 1193107077deSPrzemyslaw Czarnowski 1194107077deSPrzemyslaw Czarnowski } // namespace redfish 1195