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 18*7e860f15SJohn Edward Broadbent #include <app.hpp> 19107077deSPrzemyslaw Czarnowski #include <boost/container/flat_map.hpp> 20988fb7b2SAdrian Ambrożewicz #include <boost/process/async_pipe.hpp> 21988fb7b2SAdrian Ambrożewicz #include <boost/type_traits/has_dereference.hpp> 22107077deSPrzemyslaw Czarnowski #include <node.hpp> 23107077deSPrzemyslaw Czarnowski #include <utils/json_utils.hpp> 24107077deSPrzemyslaw Czarnowski // for GetObjectType and ManagedObjectType 25e13c2760SPrzemyslaw Czarnowski #include <account_service.hpp> 269e319cf0SAnna Platash #include <boost/url/url_view.hpp> 27107077deSPrzemyslaw Czarnowski 28107077deSPrzemyslaw Czarnowski namespace redfish 29107077deSPrzemyslaw Czarnowski 30107077deSPrzemyslaw Czarnowski { 319e319cf0SAnna Platash /** 329e319cf0SAnna Platash * @brief Function extracts transfer protocol name from URI. 339e319cf0SAnna Platash */ 349e319cf0SAnna Platash static std::string getTransferProtocolTypeFromUri(const std::string& imageUri) 359e319cf0SAnna Platash { 369e319cf0SAnna Platash try 379e319cf0SAnna Platash { 389e319cf0SAnna Platash std::string_view scheme = boost::urls::url_view(imageUri).scheme(); 399e319cf0SAnna Platash if (scheme == "smb") 409e319cf0SAnna Platash { 419e319cf0SAnna Platash return "CIFS"; 429e319cf0SAnna Platash } 439e319cf0SAnna Platash else if (scheme == "https") 449e319cf0SAnna Platash { 459e319cf0SAnna Platash return "HTTPS"; 469e319cf0SAnna Platash } 479e319cf0SAnna Platash } 489e319cf0SAnna Platash catch (std::exception& p) 499e319cf0SAnna Platash { 509e319cf0SAnna Platash BMCWEB_LOG_ERROR << p.what(); 519e319cf0SAnna Platash } 529e319cf0SAnna Platash return "None"; 539e319cf0SAnna Platash } 54107077deSPrzemyslaw Czarnowski 55107077deSPrzemyslaw Czarnowski /** 56107077deSPrzemyslaw Czarnowski * @brief Read all known properties from VM object interfaces 57107077deSPrzemyslaw Czarnowski */ 588d1b46d7Szhanghch05 static void 598d1b46d7Szhanghch05 vmParseInterfaceObject(const DbusInterfaceType& interface, 608d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& aResp) 61107077deSPrzemyslaw Czarnowski { 62107077deSPrzemyslaw Czarnowski const auto mountPointIface = 63107077deSPrzemyslaw Czarnowski interface.find("xyz.openbmc_project.VirtualMedia.MountPoint"); 64107077deSPrzemyslaw Czarnowski if (mountPointIface == interface.cend()) 65107077deSPrzemyslaw Czarnowski { 66107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Interface MountPoint not found"; 67107077deSPrzemyslaw Czarnowski return; 68107077deSPrzemyslaw Czarnowski } 69107077deSPrzemyslaw Czarnowski 70107077deSPrzemyslaw Czarnowski const auto processIface = 71107077deSPrzemyslaw Czarnowski interface.find("xyz.openbmc_project.VirtualMedia.Process"); 72107077deSPrzemyslaw Czarnowski if (processIface == interface.cend()) 73107077deSPrzemyslaw Czarnowski { 74107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Interface Process not found"; 75107077deSPrzemyslaw Czarnowski return; 76107077deSPrzemyslaw Czarnowski } 77107077deSPrzemyslaw Czarnowski 78107077deSPrzemyslaw Czarnowski const auto endpointIdProperty = mountPointIface->second.find("EndpointId"); 79107077deSPrzemyslaw Czarnowski if (endpointIdProperty == mountPointIface->second.cend()) 80107077deSPrzemyslaw Czarnowski { 81107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Property EndpointId not found"; 82107077deSPrzemyslaw Czarnowski return; 83107077deSPrzemyslaw Czarnowski } 84107077deSPrzemyslaw Czarnowski 85107077deSPrzemyslaw Czarnowski const auto activeProperty = processIface->second.find("Active"); 86107077deSPrzemyslaw Czarnowski if (activeProperty == processIface->second.cend()) 87107077deSPrzemyslaw Czarnowski { 88107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Property Active not found"; 89107077deSPrzemyslaw Czarnowski return; 90107077deSPrzemyslaw Czarnowski } 91107077deSPrzemyslaw Czarnowski 92107077deSPrzemyslaw Czarnowski const bool* activeValue = std::get_if<bool>(&activeProperty->second); 93107077deSPrzemyslaw Czarnowski if (!activeValue) 94107077deSPrzemyslaw Czarnowski { 95107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Value Active not found"; 96107077deSPrzemyslaw Czarnowski return; 97107077deSPrzemyslaw Czarnowski } 98107077deSPrzemyslaw Czarnowski 99107077deSPrzemyslaw Czarnowski const std::string* endpointIdValue = 100107077deSPrzemyslaw Czarnowski std::get_if<std::string>(&endpointIdProperty->second); 101107077deSPrzemyslaw Czarnowski if (endpointIdValue) 102107077deSPrzemyslaw Czarnowski { 103107077deSPrzemyslaw Czarnowski if (!endpointIdValue->empty()) 104107077deSPrzemyslaw Czarnowski { 105107077deSPrzemyslaw Czarnowski // Proxy mode 106d04ba325SPrzemyslaw Czarnowski aResp->res.jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] = 107d04ba325SPrzemyslaw Czarnowski *endpointIdValue; 108107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["TransferProtocolType"] = "OEM"; 109107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Inserted"] = *activeValue; 110107077deSPrzemyslaw Czarnowski if (*activeValue == true) 111107077deSPrzemyslaw Czarnowski { 112107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["ConnectedVia"] = "Applet"; 113107077deSPrzemyslaw Czarnowski } 114107077deSPrzemyslaw Czarnowski } 115107077deSPrzemyslaw Czarnowski else 116107077deSPrzemyslaw Czarnowski { 117107077deSPrzemyslaw Czarnowski // Legacy mode 1189e319cf0SAnna Platash for (const auto& property : mountPointIface->second) 1199e319cf0SAnna Platash { 1209e319cf0SAnna Platash if (property.first == "ImageURL") 121107077deSPrzemyslaw Czarnowski { 122107077deSPrzemyslaw Czarnowski const std::string* imageUrlValue = 1239e319cf0SAnna Platash std::get_if<std::string>(&property.second); 124107077deSPrzemyslaw Czarnowski if (imageUrlValue && !imageUrlValue->empty()) 125107077deSPrzemyslaw Czarnowski { 126da4784d8SPrzemyslaw Czarnowski std::filesystem::path filePath = *imageUrlValue; 127da4784d8SPrzemyslaw Czarnowski if (!filePath.has_filename()) 128da4784d8SPrzemyslaw Czarnowski { 1299e319cf0SAnna Platash // this will handle https share, which not 1309e319cf0SAnna Platash // necessarily has to have filename given. 131da4784d8SPrzemyslaw Czarnowski aResp->res.jsonValue["ImageName"] = ""; 132da4784d8SPrzemyslaw Czarnowski } 133da4784d8SPrzemyslaw Czarnowski else 134da4784d8SPrzemyslaw Czarnowski { 1359e319cf0SAnna Platash aResp->res.jsonValue["ImageName"] = 1369e319cf0SAnna Platash filePath.filename(); 137da4784d8SPrzemyslaw Czarnowski } 138da4784d8SPrzemyslaw Czarnowski 139da4784d8SPrzemyslaw Czarnowski aResp->res.jsonValue["Image"] = *imageUrlValue; 140107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Inserted"] = *activeValue; 1419e319cf0SAnna Platash aResp->res.jsonValue["TransferProtocolType"] = 1429e319cf0SAnna Platash getTransferProtocolTypeFromUri(*imageUrlValue); 1439e319cf0SAnna Platash 144107077deSPrzemyslaw Czarnowski if (*activeValue == true) 145107077deSPrzemyslaw Czarnowski { 146107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["ConnectedVia"] = "URI"; 147107077deSPrzemyslaw Czarnowski } 148107077deSPrzemyslaw Czarnowski } 149107077deSPrzemyslaw Czarnowski } 1509e319cf0SAnna Platash else if (property.first == "WriteProtected") 1519e319cf0SAnna Platash { 1529e319cf0SAnna Platash const bool* writeProtectedValue = 1539e319cf0SAnna Platash std::get_if<bool>(&property.second); 1549e319cf0SAnna Platash if (writeProtectedValue) 1559e319cf0SAnna Platash { 1569e319cf0SAnna Platash aResp->res.jsonValue["WriteProtected"] = 1579e319cf0SAnna Platash *writeProtectedValue; 1589e319cf0SAnna Platash } 1599e319cf0SAnna Platash } 1609e319cf0SAnna Platash } 161107077deSPrzemyslaw Czarnowski } 162107077deSPrzemyslaw Czarnowski } 163107077deSPrzemyslaw Czarnowski } 164107077deSPrzemyslaw Czarnowski 165107077deSPrzemyslaw Czarnowski /** 166107077deSPrzemyslaw Czarnowski * @brief Fill template for Virtual Media Item. 167107077deSPrzemyslaw Czarnowski */ 168107077deSPrzemyslaw Czarnowski static nlohmann::json vmItemTemplate(const std::string& name, 169107077deSPrzemyslaw Czarnowski const std::string& resName) 170107077deSPrzemyslaw Czarnowski { 171107077deSPrzemyslaw Czarnowski nlohmann::json item; 172107077deSPrzemyslaw Czarnowski item["@odata.id"] = 173107077deSPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + resName; 174d04ba325SPrzemyslaw Czarnowski item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia"; 175107077deSPrzemyslaw Czarnowski item["Name"] = "Virtual Removable Media"; 176107077deSPrzemyslaw Czarnowski item["Id"] = resName; 177107077deSPrzemyslaw Czarnowski item["WriteProtected"] = true; 178107077deSPrzemyslaw Czarnowski item["MediaTypes"] = {"CD", "USBStick"}; 179107077deSPrzemyslaw Czarnowski item["TransferMethod"] = "Stream"; 180d04ba325SPrzemyslaw Czarnowski item["Oem"]["OpenBMC"]["@odata.type"] = 181d04ba325SPrzemyslaw Czarnowski "#OemVirtualMedia.v1_0_0.VirtualMedia"; 182107077deSPrzemyslaw Czarnowski 183107077deSPrzemyslaw Czarnowski return item; 184107077deSPrzemyslaw Czarnowski } 185107077deSPrzemyslaw Czarnowski 186107077deSPrzemyslaw Czarnowski /** 187107077deSPrzemyslaw Czarnowski * @brief Fills collection data 188107077deSPrzemyslaw Czarnowski */ 1898d1b46d7Szhanghch05 static void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp, 190107077deSPrzemyslaw Czarnowski const std::string& service, 191107077deSPrzemyslaw Czarnowski const std::string& name) 192107077deSPrzemyslaw Czarnowski { 193107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Get available Virtual Media resources."; 194107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 195107077deSPrzemyslaw Czarnowski [name, aResp{std::move(aResp)}](const boost::system::error_code ec, 196107077deSPrzemyslaw Czarnowski ManagedObjectType& subtree) { 197107077deSPrzemyslaw Czarnowski if (ec) 198107077deSPrzemyslaw Czarnowski { 199107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 200107077deSPrzemyslaw Czarnowski return; 201107077deSPrzemyslaw Czarnowski } 202107077deSPrzemyslaw Czarnowski nlohmann::json& members = aResp->res.jsonValue["Members"]; 203107077deSPrzemyslaw Czarnowski members = nlohmann::json::array(); 204107077deSPrzemyslaw Czarnowski 205107077deSPrzemyslaw Czarnowski for (const auto& object : subtree) 206107077deSPrzemyslaw Czarnowski { 207107077deSPrzemyslaw Czarnowski nlohmann::json item; 2082dfd18efSEd Tanous std::string path = object.first.filename(); 2092dfd18efSEd Tanous if (path.empty()) 210107077deSPrzemyslaw Czarnowski { 211107077deSPrzemyslaw Czarnowski continue; 212107077deSPrzemyslaw Czarnowski } 213107077deSPrzemyslaw Czarnowski 2142dfd18efSEd Tanous item["@odata.id"] = 215788ca507SAppaRao Puli "/redfish/v1/Managers/" + name + "/VirtualMedia/" + path; 216107077deSPrzemyslaw Czarnowski 217107077deSPrzemyslaw Czarnowski members.emplace_back(std::move(item)); 218107077deSPrzemyslaw Czarnowski } 219107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Members@odata.count"] = members.size(); 220107077deSPrzemyslaw Czarnowski }, 221107077deSPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 222107077deSPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 223107077deSPrzemyslaw Czarnowski } 224107077deSPrzemyslaw Czarnowski 225107077deSPrzemyslaw Czarnowski /** 226107077deSPrzemyslaw Czarnowski * @brief Fills data for specific resource 227107077deSPrzemyslaw Czarnowski */ 2288d1b46d7Szhanghch05 static void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 229107077deSPrzemyslaw Czarnowski const std::string& service, const std::string& name, 230107077deSPrzemyslaw Czarnowski const std::string& resName) 231107077deSPrzemyslaw Czarnowski { 232107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Get Virtual Media resource data."; 233107077deSPrzemyslaw Czarnowski 234107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 235107077deSPrzemyslaw Czarnowski [resName, name, aResp](const boost::system::error_code ec, 236107077deSPrzemyslaw Czarnowski ManagedObjectType& subtree) { 237107077deSPrzemyslaw Czarnowski if (ec) 238107077deSPrzemyslaw Czarnowski { 239107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 240e13c2760SPrzemyslaw Czarnowski 241107077deSPrzemyslaw Czarnowski return; 242107077deSPrzemyslaw Czarnowski } 243107077deSPrzemyslaw Czarnowski 244107077deSPrzemyslaw Czarnowski for (auto& item : subtree) 245107077deSPrzemyslaw Czarnowski { 2462dfd18efSEd Tanous std::string thispath = item.first.filename(); 2472dfd18efSEd Tanous if (thispath.empty()) 248107077deSPrzemyslaw Czarnowski { 249107077deSPrzemyslaw Czarnowski continue; 250107077deSPrzemyslaw Czarnowski } 251107077deSPrzemyslaw Czarnowski 2522dfd18efSEd Tanous if (thispath != resName) 253107077deSPrzemyslaw Czarnowski { 254107077deSPrzemyslaw Czarnowski continue; 255107077deSPrzemyslaw Czarnowski } 256107077deSPrzemyslaw Czarnowski 2571a6258dcSPrzemyslaw Czarnowski // "Legacy"/"Proxy" 2581a6258dcSPrzemyslaw Czarnowski auto mode = item.first.parent_path(); 2591a6258dcSPrzemyslaw Czarnowski // "VirtualMedia" 2601a6258dcSPrzemyslaw Czarnowski auto type = mode.parent_path(); 2611a6258dcSPrzemyslaw Czarnowski if (mode.filename().empty() || type.filename().empty()) 2621a6258dcSPrzemyslaw Czarnowski { 2631a6258dcSPrzemyslaw Czarnowski continue; 2641a6258dcSPrzemyslaw Czarnowski } 2651a6258dcSPrzemyslaw Czarnowski 2661a6258dcSPrzemyslaw Czarnowski if (type.filename() != "VirtualMedia") 2671a6258dcSPrzemyslaw Czarnowski { 2681a6258dcSPrzemyslaw Czarnowski continue; 2691a6258dcSPrzemyslaw Czarnowski } 2701a6258dcSPrzemyslaw Czarnowski 271107077deSPrzemyslaw Czarnowski aResp->res.jsonValue = vmItemTemplate(name, resName); 272107077deSPrzemyslaw Czarnowski 273e13c2760SPrzemyslaw Czarnowski // Check if dbus path is Legacy type 2741a6258dcSPrzemyslaw Czarnowski if (mode.filename() == "Legacy") 275e13c2760SPrzemyslaw Czarnowski { 276e13c2760SPrzemyslaw Czarnowski aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"] 277e13c2760SPrzemyslaw Czarnowski ["target"] = 278e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + 279e13c2760SPrzemyslaw Czarnowski resName + "/Actions/VirtualMedia.InsertMedia"; 280e13c2760SPrzemyslaw Czarnowski } 281e13c2760SPrzemyslaw Czarnowski 282107077deSPrzemyslaw Czarnowski vmParseInterfaceObject(item.second, aResp); 283107077deSPrzemyslaw Czarnowski 284e13c2760SPrzemyslaw Czarnowski aResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"] 285e13c2760SPrzemyslaw Czarnowski ["target"] = 286e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + 287e13c2760SPrzemyslaw Czarnowski resName + "/Actions/VirtualMedia.EjectMedia"; 288e13c2760SPrzemyslaw Czarnowski 289107077deSPrzemyslaw Czarnowski return; 290107077deSPrzemyslaw Czarnowski } 291107077deSPrzemyslaw Czarnowski 292107077deSPrzemyslaw Czarnowski messages::resourceNotFound( 293d04ba325SPrzemyslaw Czarnowski aResp->res, "#VirtualMedia.v1_3_0.VirtualMedia", resName); 294107077deSPrzemyslaw Czarnowski }, 295107077deSPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 296107077deSPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 297107077deSPrzemyslaw Czarnowski } 298107077deSPrzemyslaw Czarnowski 299e13c2760SPrzemyslaw Czarnowski /** 300e13c2760SPrzemyslaw Czarnowski @brief InsertMedia action class 301e13c2760SPrzemyslaw Czarnowski */ 302e13c2760SPrzemyslaw Czarnowski class VirtualMediaActionInsertMedia : public Node 303e13c2760SPrzemyslaw Czarnowski { 304e13c2760SPrzemyslaw Czarnowski public: 30552cc112dSEd Tanous VirtualMediaActionInsertMedia(App& app) : 306e13c2760SPrzemyslaw Czarnowski Node(app, 307e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/" 308e13c2760SPrzemyslaw Czarnowski "VirtualMedia.InsertMedia", 309e13c2760SPrzemyslaw Czarnowski std::string(), std::string()) 310e13c2760SPrzemyslaw Czarnowski { 311e13c2760SPrzemyslaw Czarnowski entityPrivileges = { 312e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 313e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 314e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 315e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 316e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 317e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 318e13c2760SPrzemyslaw Czarnowski } 319e13c2760SPrzemyslaw Czarnowski 320e13c2760SPrzemyslaw Czarnowski private: 321e13c2760SPrzemyslaw Czarnowski /** 322c6f4e017SAgata Olender * @brief Transfer protocols supported for InsertMedia action. 323c6f4e017SAgata Olender * 324c6f4e017SAgata Olender */ 325c6f4e017SAgata Olender enum class TransferProtocol 326c6f4e017SAgata Olender { 327c6f4e017SAgata Olender https, 328c6f4e017SAgata Olender smb, 329c6f4e017SAgata Olender invalid 330c6f4e017SAgata Olender }; 331c6f4e017SAgata Olender 332c6f4e017SAgata Olender /** 333c6f4e017SAgata Olender * @brief Function extracts transfer protocol type from URI. 334c6f4e017SAgata Olender * 335c6f4e017SAgata Olender */ 336c6f4e017SAgata Olender std::optional<TransferProtocol> 337c6f4e017SAgata Olender getTransferProtocolFromUri(const std::string& imageUri) 338c6f4e017SAgata Olender { 3399e319cf0SAnna Platash try 3409e319cf0SAnna Platash { 3419e319cf0SAnna Platash std::string_view scheme = boost::urls::url_view(imageUri).scheme(); 3429e319cf0SAnna Platash if (scheme == "smb") 343c6f4e017SAgata Olender { 344c6f4e017SAgata Olender return TransferProtocol::smb; 345c6f4e017SAgata Olender } 34681ce609eSEd Tanous if (scheme == "https") 347c6f4e017SAgata Olender { 348c6f4e017SAgata Olender return TransferProtocol::https; 349c6f4e017SAgata Olender } 3509e319cf0SAnna Platash else if (!scheme.empty()) 351c6f4e017SAgata Olender { 352c6f4e017SAgata Olender return TransferProtocol::invalid; 353c6f4e017SAgata Olender } 354c6f4e017SAgata Olender } 3559e319cf0SAnna Platash catch (std::exception& p) 3569e319cf0SAnna Platash { 3579e319cf0SAnna Platash BMCWEB_LOG_ERROR << p.what(); 3589e319cf0SAnna Platash } 3599e319cf0SAnna Platash 3609e319cf0SAnna Platash return {}; 361c6f4e017SAgata Olender } 362c6f4e017SAgata Olender 363c6f4e017SAgata Olender /** 364c6f4e017SAgata Olender * @brief Function convert transfer protocol from string param. 365c6f4e017SAgata Olender * 366c6f4e017SAgata Olender */ 367c6f4e017SAgata Olender std::optional<TransferProtocol> getTransferProtocolFromParam( 368c6f4e017SAgata Olender const std::optional<std::string>& transferProtocolType) 369c6f4e017SAgata Olender { 370c6f4e017SAgata Olender if (transferProtocolType == std::nullopt) 371c6f4e017SAgata Olender { 372c6f4e017SAgata Olender return {}; 373c6f4e017SAgata Olender } 374c6f4e017SAgata Olender 375c6f4e017SAgata Olender if (*transferProtocolType == "CIFS") 376c6f4e017SAgata Olender { 377c6f4e017SAgata Olender return TransferProtocol::smb; 378c6f4e017SAgata Olender } 379c6f4e017SAgata Olender 380c6f4e017SAgata Olender if (*transferProtocolType == "HTTPS") 381c6f4e017SAgata Olender { 382c6f4e017SAgata Olender return TransferProtocol::https; 383c6f4e017SAgata Olender } 384c6f4e017SAgata Olender 385c6f4e017SAgata Olender return TransferProtocol::invalid; 386c6f4e017SAgata Olender } 387c6f4e017SAgata Olender 388c6f4e017SAgata Olender /** 389c6f4e017SAgata Olender * @brief Function extends URI with transfer protocol type. 390c6f4e017SAgata Olender * 391c6f4e017SAgata Olender */ 39281ce609eSEd Tanous std::string 393c6f4e017SAgata Olender getUriWithTransferProtocol(const std::string& imageUri, 394c6f4e017SAgata Olender const TransferProtocol& transferProtocol) 395c6f4e017SAgata Olender { 396c6f4e017SAgata Olender if (transferProtocol == TransferProtocol::smb) 397c6f4e017SAgata Olender { 398c6f4e017SAgata Olender return "smb://" + imageUri; 399c6f4e017SAgata Olender } 400c6f4e017SAgata Olender 401c6f4e017SAgata Olender if (transferProtocol == TransferProtocol::https) 402c6f4e017SAgata Olender { 403c6f4e017SAgata Olender return "https://" + imageUri; 404c6f4e017SAgata Olender } 405c6f4e017SAgata Olender 406c6f4e017SAgata Olender return imageUri; 407c6f4e017SAgata Olender } 408c6f4e017SAgata Olender 409c6f4e017SAgata Olender /** 410c6f4e017SAgata Olender * @brief Function validate parameters of insert media request. 411c6f4e017SAgata Olender * 412c6f4e017SAgata Olender */ 4138d1b46d7Szhanghch05 bool validateParams(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4148d1b46d7Szhanghch05 std::string& imageUrl, 415c6f4e017SAgata Olender const std::optional<bool>& inserted, 416c6f4e017SAgata Olender const std::optional<std::string>& transferMethod, 417c6f4e017SAgata Olender const std::optional<std::string>& transferProtocolType) 418c6f4e017SAgata Olender { 419c6f4e017SAgata Olender BMCWEB_LOG_DEBUG << "Validation started"; 420c6f4e017SAgata Olender // required param imageUrl must not be empty 421c6f4e017SAgata Olender if (imageUrl.empty()) 422c6f4e017SAgata Olender { 423c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter Image is empty."; 424c6f4e017SAgata Olender 4258d1b46d7Szhanghch05 messages::propertyValueFormatError(asyncResp->res, "<empty>", 4268d1b46d7Szhanghch05 "Image"); 427c6f4e017SAgata Olender 428c6f4e017SAgata Olender return false; 429c6f4e017SAgata Olender } 430c6f4e017SAgata Olender 431c6f4e017SAgata Olender // optional param inserted must be true 432c6f4e017SAgata Olender if ((inserted != std::nullopt) && (*inserted != true)) 433c6f4e017SAgata Olender { 434c6f4e017SAgata Olender BMCWEB_LOG_ERROR 435c6f4e017SAgata Olender << "Request action optional parameter Inserted must be true."; 436c6f4e017SAgata Olender 4378d1b46d7Szhanghch05 messages::actionParameterNotSupported(asyncResp->res, "Inserted", 438c6f4e017SAgata Olender "InsertMedia"); 439c6f4e017SAgata Olender 440c6f4e017SAgata Olender return false; 441c6f4e017SAgata Olender } 442c6f4e017SAgata Olender 443c6f4e017SAgata Olender // optional param transferMethod must be stream 444c6f4e017SAgata Olender if ((transferMethod != std::nullopt) && (*transferMethod != "Stream")) 445c6f4e017SAgata Olender { 446c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action optional parameter " 447c6f4e017SAgata Olender "TransferMethod must be Stream."; 448c6f4e017SAgata Olender 4498d1b46d7Szhanghch05 messages::actionParameterNotSupported( 4508d1b46d7Szhanghch05 asyncResp->res, "TransferMethod", "InsertMedia"); 451c6f4e017SAgata Olender 452c6f4e017SAgata Olender return false; 453c6f4e017SAgata Olender } 454c6f4e017SAgata Olender 455c6f4e017SAgata Olender std::optional<TransferProtocol> uriTransferProtocolType = 456c6f4e017SAgata Olender getTransferProtocolFromUri(imageUrl); 457c6f4e017SAgata Olender 458c6f4e017SAgata Olender std::optional<TransferProtocol> paramTransferProtocolType = 459c6f4e017SAgata Olender getTransferProtocolFromParam(transferProtocolType); 460c6f4e017SAgata Olender 461c6f4e017SAgata Olender // ImageUrl does not contain valid protocol type 462c6f4e017SAgata Olender if (*uriTransferProtocolType == TransferProtocol::invalid) 463c6f4e017SAgata Olender { 464c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must " 465c6f4e017SAgata Olender "contain specified protocol type from list: " 466c6f4e017SAgata Olender "(smb, https)."; 467c6f4e017SAgata Olender 4688d1b46d7Szhanghch05 messages::resourceAtUriInUnknownFormat(asyncResp->res, imageUrl); 469c6f4e017SAgata Olender 470c6f4e017SAgata Olender return false; 471c6f4e017SAgata Olender } 472c6f4e017SAgata Olender 473c6f4e017SAgata Olender // transferProtocolType should contain value from list 474c6f4e017SAgata Olender if (*paramTransferProtocolType == TransferProtocol::invalid) 475c6f4e017SAgata Olender { 476c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType " 477c6f4e017SAgata Olender "must be provided with value from list: " 478c6f4e017SAgata Olender "(CIFS, HTTPS)."; 479c6f4e017SAgata Olender 4808d1b46d7Szhanghch05 messages::propertyValueNotInList( 4818d1b46d7Szhanghch05 asyncResp->res, *transferProtocolType, "TransferProtocolType"); 482c6f4e017SAgata Olender return false; 483c6f4e017SAgata Olender } 484c6f4e017SAgata Olender 485c6f4e017SAgata Olender // valid transfer protocol not provided either with URI nor param 486c6f4e017SAgata Olender if ((uriTransferProtocolType == std::nullopt) && 487c6f4e017SAgata Olender (paramTransferProtocolType == std::nullopt)) 488c6f4e017SAgata Olender { 489c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must " 490c6f4e017SAgata Olender "contain specified protocol type or param " 491c6f4e017SAgata Olender "TransferProtocolType must be provided."; 492c6f4e017SAgata Olender 4938d1b46d7Szhanghch05 messages::resourceAtUriInUnknownFormat(asyncResp->res, imageUrl); 494c6f4e017SAgata Olender 495c6f4e017SAgata Olender return false; 496c6f4e017SAgata Olender } 497c6f4e017SAgata Olender 498c6f4e017SAgata Olender // valid transfer protocol provided both with URI and param 499c6f4e017SAgata Olender if ((paramTransferProtocolType != std::nullopt) && 500c6f4e017SAgata Olender (uriTransferProtocolType != std::nullopt)) 501c6f4e017SAgata Olender { 502c6f4e017SAgata Olender // check if protocol is the same for URI and param 503c6f4e017SAgata Olender if (*paramTransferProtocolType != *uriTransferProtocolType) 504c6f4e017SAgata Olender { 505c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter " 506c6f4e017SAgata Olender "TransferProtocolType must contain the " 507c6f4e017SAgata Olender "same protocol type as protocol type " 508c6f4e017SAgata Olender "provided with param imageUrl."; 509c6f4e017SAgata Olender 510c6f4e017SAgata Olender messages::actionParameterValueTypeError( 5118d1b46d7Szhanghch05 asyncResp->res, *transferProtocolType, 5128d1b46d7Szhanghch05 "TransferProtocolType", "InsertMedia"); 513c6f4e017SAgata Olender 514c6f4e017SAgata Olender return false; 515c6f4e017SAgata Olender } 516c6f4e017SAgata Olender } 517c6f4e017SAgata Olender 518c6f4e017SAgata Olender // validation passed 519c6f4e017SAgata Olender // add protocol to URI if needed 520c6f4e017SAgata Olender if (uriTransferProtocolType == std::nullopt) 521c6f4e017SAgata Olender { 522c6f4e017SAgata Olender imageUrl = getUriWithTransferProtocol(imageUrl, 523c6f4e017SAgata Olender *paramTransferProtocolType); 524c6f4e017SAgata Olender } 525c6f4e017SAgata Olender 526c6f4e017SAgata Olender return true; 527c6f4e017SAgata Olender } 528c6f4e017SAgata Olender 529c6f4e017SAgata Olender /** 530e13c2760SPrzemyslaw Czarnowski * @brief Function handles POST method request. 531e13c2760SPrzemyslaw Czarnowski * 532e13c2760SPrzemyslaw Czarnowski * Analyzes POST body message before sends Reset request data to dbus. 533e13c2760SPrzemyslaw Czarnowski */ 5348d1b46d7Szhanghch05 void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5358d1b46d7Szhanghch05 const crow::Request& req, 536e13c2760SPrzemyslaw Czarnowski const std::vector<std::string>& params) override 537e13c2760SPrzemyslaw Czarnowski { 538e13c2760SPrzemyslaw Czarnowski if (params.size() != 2) 539e13c2760SPrzemyslaw Czarnowski { 5408d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 541e13c2760SPrzemyslaw Czarnowski return; 542e13c2760SPrzemyslaw Czarnowski } 543e13c2760SPrzemyslaw Czarnowski 544e13c2760SPrzemyslaw Czarnowski // take resource name from URL 545e13c2760SPrzemyslaw Czarnowski const std::string& resName = params[1]; 546e13c2760SPrzemyslaw Czarnowski 547e13c2760SPrzemyslaw Czarnowski if (params[0] != "bmc") 548e13c2760SPrzemyslaw Czarnowski { 5498d1b46d7Szhanghch05 messages::resourceNotFound(asyncResp->res, "VirtualMedia.Insert", 5508d1b46d7Szhanghch05 resName); 551e13c2760SPrzemyslaw Czarnowski 552e13c2760SPrzemyslaw Czarnowski return; 553e13c2760SPrzemyslaw Czarnowski } 554e13c2760SPrzemyslaw Czarnowski 555e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 5568d1b46d7Szhanghch05 [this, asyncResp, req, 557e13c2760SPrzemyslaw Czarnowski resName](const boost::system::error_code ec, 558e13c2760SPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 559e13c2760SPrzemyslaw Czarnowski if (ec) 560e13c2760SPrzemyslaw Czarnowski { 561e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 562e13c2760SPrzemyslaw Czarnowski << ec; 5638d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 564e13c2760SPrzemyslaw Czarnowski 565e13c2760SPrzemyslaw Czarnowski return; 566e13c2760SPrzemyslaw Czarnowski } 567e13c2760SPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 568e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 569e13c2760SPrzemyslaw Czarnowski 570e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 57181ce609eSEd Tanous [this, service, resName, req, 5728d1b46d7Szhanghch05 asyncResp](const boost::system::error_code ec, 573e13c2760SPrzemyslaw Czarnowski ManagedObjectType& subtree) { 574e13c2760SPrzemyslaw Czarnowski if (ec) 575e13c2760SPrzemyslaw Czarnowski { 576e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 577e13c2760SPrzemyslaw Czarnowski 578e13c2760SPrzemyslaw Czarnowski return; 579e13c2760SPrzemyslaw Czarnowski } 580e13c2760SPrzemyslaw Czarnowski 581e13c2760SPrzemyslaw Czarnowski for (const auto& object : subtree) 582e13c2760SPrzemyslaw Czarnowski { 583e13c2760SPrzemyslaw Czarnowski const std::string& path = 584e13c2760SPrzemyslaw Czarnowski static_cast<const std::string&>(object.first); 585e13c2760SPrzemyslaw Czarnowski 586f23b7296SEd Tanous std::size_t lastIndex = path.rfind('/'); 587e13c2760SPrzemyslaw Czarnowski if (lastIndex == std::string::npos) 588e13c2760SPrzemyslaw Czarnowski { 589e13c2760SPrzemyslaw Czarnowski continue; 590e13c2760SPrzemyslaw Czarnowski } 591e13c2760SPrzemyslaw Czarnowski 592e13c2760SPrzemyslaw Czarnowski lastIndex += 1; 593e13c2760SPrzemyslaw Czarnowski 594e13c2760SPrzemyslaw Czarnowski if (path.substr(lastIndex) == resName) 595e13c2760SPrzemyslaw Czarnowski { 596e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Proxy"); 597e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 598e13c2760SPrzemyslaw Czarnowski { 599e13c2760SPrzemyslaw Czarnowski // Not possible in proxy mode 600e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "InsertMedia not " 601e13c2760SPrzemyslaw Czarnowski "allowed in proxy mode"; 602e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound( 6038d1b46d7Szhanghch05 asyncResp->res, 6048d1b46d7Szhanghch05 "VirtualMedia.InsertMedia", resName); 605e13c2760SPrzemyslaw Czarnowski 606e13c2760SPrzemyslaw Czarnowski return; 607e13c2760SPrzemyslaw Czarnowski } 608e13c2760SPrzemyslaw Czarnowski 609e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Legacy"); 610c6f4e017SAgata Olender if (lastIndex == std::string::npos) 611e13c2760SPrzemyslaw Czarnowski { 612c6f4e017SAgata Olender continue; 613c6f4e017SAgata Olender } 614c6f4e017SAgata Olender 615e13c2760SPrzemyslaw Czarnowski // Legacy mode 616e13c2760SPrzemyslaw Czarnowski std::string imageUrl; 617c6f4e017SAgata Olender std::optional<std::string> userName; 618c6f4e017SAgata Olender std::optional<std::string> password; 619c6f4e017SAgata Olender std::optional<std::string> transferMethod; 620c6f4e017SAgata Olender std::optional<std::string> transferProtocolType; 621c6f4e017SAgata Olender std::optional<bool> writeProtected = true; 622c6f4e017SAgata Olender std::optional<bool> inserted; 623e13c2760SPrzemyslaw Czarnowski 6244e0453b1SGunnar Mills // Read obligatory parameters (url of image) 625d6da5bebSAdrian Ambrożewicz if (!json_util::readJson( 6268d1b46d7Szhanghch05 req, asyncResp->res, "Image", imageUrl, 627988fb7b2SAdrian Ambrożewicz "WriteProtected", writeProtected, 628988fb7b2SAdrian Ambrożewicz "UserName", userName, "Password", 629c6f4e017SAgata Olender password, "Inserted", inserted, 630c6f4e017SAgata Olender "TransferMethod", transferMethod, 631c6f4e017SAgata Olender "TransferProtocolType", 632c6f4e017SAgata Olender transferProtocolType)) 633e13c2760SPrzemyslaw Czarnowski { 634c6f4e017SAgata Olender BMCWEB_LOG_DEBUG << "Image is not provided"; 635e13c2760SPrzemyslaw Czarnowski return; 636e13c2760SPrzemyslaw Czarnowski } 637e13c2760SPrzemyslaw Czarnowski 638c6f4e017SAgata Olender bool paramsValid = validateParams( 6398d1b46d7Szhanghch05 asyncResp->res, imageUrl, inserted, 640c6f4e017SAgata Olender transferMethod, transferProtocolType); 641c6f4e017SAgata Olender 642c6f4e017SAgata Olender if (paramsValid == false) 643e13c2760SPrzemyslaw Czarnowski { 644e13c2760SPrzemyslaw Czarnowski return; 645e13c2760SPrzemyslaw Czarnowski } 646e13c2760SPrzemyslaw Czarnowski 647c6f4e017SAgata Olender // manager is irrelevant for VirtualMedia dbus 648c6f4e017SAgata Olender // calls 6498d1b46d7Szhanghch05 doMountVmLegacy(asyncResp, service, resName, 650c6f4e017SAgata Olender imageUrl, !(*writeProtected), 65181ce609eSEd Tanous std::move(*userName), 65281ce609eSEd Tanous std::move(*password)); 653e13c2760SPrzemyslaw Czarnowski 654e13c2760SPrzemyslaw Czarnowski return; 655e13c2760SPrzemyslaw Czarnowski } 656e13c2760SPrzemyslaw Czarnowski } 657e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Parent item not found"; 6588d1b46d7Szhanghch05 messages::resourceNotFound(asyncResp->res, 6598d1b46d7Szhanghch05 "VirtualMedia", resName); 660e13c2760SPrzemyslaw Czarnowski }, 661e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 662e13c2760SPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 663e13c2760SPrzemyslaw Czarnowski }, 664e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 665e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 666e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 667e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 668e13c2760SPrzemyslaw Czarnowski } 669e13c2760SPrzemyslaw Czarnowski 6701214b7e7SGunnar Mills template <typename T> 6711214b7e7SGunnar Mills static void secureCleanup(T& value) 672988fb7b2SAdrian Ambrożewicz { 673988fb7b2SAdrian Ambrożewicz auto raw = const_cast<typename T::value_type*>(value.data()); 674988fb7b2SAdrian Ambrożewicz explicit_bzero(raw, value.size() * sizeof(*raw)); 675988fb7b2SAdrian Ambrożewicz } 676988fb7b2SAdrian Ambrożewicz 677988fb7b2SAdrian Ambrożewicz class Credentials 678988fb7b2SAdrian Ambrożewicz { 679988fb7b2SAdrian Ambrożewicz public: 680988fb7b2SAdrian Ambrożewicz Credentials(std::string&& user, std::string&& password) : 681988fb7b2SAdrian Ambrożewicz userBuf(std::move(user)), passBuf(std::move(password)) 6821214b7e7SGunnar Mills {} 683988fb7b2SAdrian Ambrożewicz 684988fb7b2SAdrian Ambrożewicz ~Credentials() 685988fb7b2SAdrian Ambrożewicz { 686988fb7b2SAdrian Ambrożewicz secureCleanup(userBuf); 687988fb7b2SAdrian Ambrożewicz secureCleanup(passBuf); 688988fb7b2SAdrian Ambrożewicz } 689988fb7b2SAdrian Ambrożewicz 690988fb7b2SAdrian Ambrożewicz const std::string& user() 691988fb7b2SAdrian Ambrożewicz { 692988fb7b2SAdrian Ambrożewicz return userBuf; 693988fb7b2SAdrian Ambrożewicz } 694988fb7b2SAdrian Ambrożewicz 695988fb7b2SAdrian Ambrożewicz const std::string& password() 696988fb7b2SAdrian Ambrożewicz { 697988fb7b2SAdrian Ambrożewicz return passBuf; 698988fb7b2SAdrian Ambrożewicz } 699988fb7b2SAdrian Ambrożewicz 700988fb7b2SAdrian Ambrożewicz private: 701988fb7b2SAdrian Ambrożewicz Credentials() = delete; 702988fb7b2SAdrian Ambrożewicz Credentials(const Credentials&) = delete; 703988fb7b2SAdrian Ambrożewicz Credentials& operator=(const Credentials&) = delete; 704988fb7b2SAdrian Ambrożewicz 705988fb7b2SAdrian Ambrożewicz std::string userBuf; 706988fb7b2SAdrian Ambrożewicz std::string passBuf; 707988fb7b2SAdrian Ambrożewicz }; 708988fb7b2SAdrian Ambrożewicz 709988fb7b2SAdrian Ambrożewicz class CredentialsProvider 710988fb7b2SAdrian Ambrożewicz { 711988fb7b2SAdrian Ambrożewicz public: 7121214b7e7SGunnar Mills template <typename T> 7131214b7e7SGunnar Mills struct Deleter 714988fb7b2SAdrian Ambrożewicz { 715988fb7b2SAdrian Ambrożewicz void operator()(T* buff) const 716988fb7b2SAdrian Ambrożewicz { 717988fb7b2SAdrian Ambrożewicz if (buff) 718988fb7b2SAdrian Ambrożewicz { 719988fb7b2SAdrian Ambrożewicz secureCleanup(*buff); 720988fb7b2SAdrian Ambrożewicz delete buff; 721988fb7b2SAdrian Ambrożewicz } 722988fb7b2SAdrian Ambrożewicz } 723988fb7b2SAdrian Ambrożewicz }; 724988fb7b2SAdrian Ambrożewicz 725988fb7b2SAdrian Ambrożewicz using Buffer = std::vector<char>; 726988fb7b2SAdrian Ambrożewicz using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>; 727988fb7b2SAdrian Ambrożewicz // Using explicit definition instead of std::function to avoid implicit 728988fb7b2SAdrian Ambrożewicz // conversions eg. stack copy instead of reference 729988fb7b2SAdrian Ambrożewicz using FormatterFunc = void(const std::string& username, 730988fb7b2SAdrian Ambrożewicz const std::string& password, Buffer& dest); 731988fb7b2SAdrian Ambrożewicz 732988fb7b2SAdrian Ambrożewicz CredentialsProvider(std::string&& user, std::string&& password) : 733988fb7b2SAdrian Ambrożewicz credentials(std::move(user), std::move(password)) 7341214b7e7SGunnar Mills {} 735988fb7b2SAdrian Ambrożewicz 736988fb7b2SAdrian Ambrożewicz const std::string& user() 737988fb7b2SAdrian Ambrożewicz { 738988fb7b2SAdrian Ambrożewicz return credentials.user(); 739988fb7b2SAdrian Ambrożewicz } 740988fb7b2SAdrian Ambrożewicz 741988fb7b2SAdrian Ambrożewicz const std::string& password() 742988fb7b2SAdrian Ambrożewicz { 743988fb7b2SAdrian Ambrożewicz return credentials.password(); 744988fb7b2SAdrian Ambrożewicz } 745988fb7b2SAdrian Ambrożewicz 74681ce609eSEd Tanous SecureBuffer pack(FormatterFunc formatter) 747988fb7b2SAdrian Ambrożewicz { 748988fb7b2SAdrian Ambrożewicz SecureBuffer packed{new Buffer{}}; 749988fb7b2SAdrian Ambrożewicz if (formatter) 750988fb7b2SAdrian Ambrożewicz { 751988fb7b2SAdrian Ambrożewicz formatter(credentials.user(), credentials.password(), *packed); 752988fb7b2SAdrian Ambrożewicz } 753988fb7b2SAdrian Ambrożewicz 754988fb7b2SAdrian Ambrożewicz return packed; 755988fb7b2SAdrian Ambrożewicz } 756988fb7b2SAdrian Ambrożewicz 757988fb7b2SAdrian Ambrożewicz private: 758988fb7b2SAdrian Ambrożewicz Credentials credentials; 759988fb7b2SAdrian Ambrożewicz }; 760988fb7b2SAdrian Ambrożewicz 761988fb7b2SAdrian Ambrożewicz // Wrapper for boost::async_pipe ensuring proper pipe cleanup 7621214b7e7SGunnar Mills template <typename Buffer> 7631214b7e7SGunnar Mills class Pipe 764988fb7b2SAdrian Ambrożewicz { 765988fb7b2SAdrian Ambrożewicz public: 766988fb7b2SAdrian Ambrożewicz using unix_fd = sdbusplus::message::unix_fd; 767988fb7b2SAdrian Ambrożewicz 768988fb7b2SAdrian Ambrożewicz Pipe(boost::asio::io_context& io, Buffer&& buffer) : 769988fb7b2SAdrian Ambrożewicz impl(io), buffer{std::move(buffer)} 7701214b7e7SGunnar Mills {} 771988fb7b2SAdrian Ambrożewicz 772988fb7b2SAdrian Ambrożewicz ~Pipe() 773988fb7b2SAdrian Ambrożewicz { 774988fb7b2SAdrian Ambrożewicz // Named pipe needs to be explicitly removed 775988fb7b2SAdrian Ambrożewicz impl.close(); 776988fb7b2SAdrian Ambrożewicz } 777988fb7b2SAdrian Ambrożewicz 778988fb7b2SAdrian Ambrożewicz unix_fd fd() 779988fb7b2SAdrian Ambrożewicz { 780988fb7b2SAdrian Ambrożewicz return unix_fd{impl.native_source()}; 781988fb7b2SAdrian Ambrożewicz } 782988fb7b2SAdrian Ambrożewicz 783988fb7b2SAdrian Ambrożewicz template <typename WriteHandler> 78481ce609eSEd Tanous void asyncWrite(WriteHandler&& handler) 785988fb7b2SAdrian Ambrożewicz { 786988fb7b2SAdrian Ambrożewicz impl.async_write_some(data(), std::forward<WriteHandler>(handler)); 787988fb7b2SAdrian Ambrożewicz } 788988fb7b2SAdrian Ambrożewicz 789988fb7b2SAdrian Ambrożewicz private: 790988fb7b2SAdrian Ambrożewicz // Specialization for pointer types 791988fb7b2SAdrian Ambrożewicz template <typename B = Buffer> 792988fb7b2SAdrian Ambrożewicz typename std::enable_if<boost::has_dereference<B>::value, 793988fb7b2SAdrian Ambrożewicz boost::asio::const_buffer>::type 794988fb7b2SAdrian Ambrożewicz data() 795988fb7b2SAdrian Ambrożewicz { 796988fb7b2SAdrian Ambrożewicz return boost::asio::buffer(*buffer); 797988fb7b2SAdrian Ambrożewicz } 798988fb7b2SAdrian Ambrożewicz 799988fb7b2SAdrian Ambrożewicz template <typename B = Buffer> 800988fb7b2SAdrian Ambrożewicz typename std::enable_if<!boost::has_dereference<B>::value, 801988fb7b2SAdrian Ambrożewicz boost::asio::const_buffer>::type 802988fb7b2SAdrian Ambrożewicz data() 803988fb7b2SAdrian Ambrożewicz { 804988fb7b2SAdrian Ambrożewicz return boost::asio::buffer(buffer); 805988fb7b2SAdrian Ambrożewicz } 806988fb7b2SAdrian Ambrożewicz 807988fb7b2SAdrian Ambrożewicz const std::string name; 808988fb7b2SAdrian Ambrożewicz boost::process::async_pipe impl; 809988fb7b2SAdrian Ambrożewicz Buffer buffer; 810988fb7b2SAdrian Ambrożewicz }; 811988fb7b2SAdrian Ambrożewicz 812e13c2760SPrzemyslaw Czarnowski /** 813e13c2760SPrzemyslaw Czarnowski * @brief Function transceives data with dbus directly. 814e13c2760SPrzemyslaw Czarnowski * 815e13c2760SPrzemyslaw Czarnowski * All BMC state properties will be retrieved before sending reset request. 816e13c2760SPrzemyslaw Czarnowski */ 8178d1b46d7Szhanghch05 void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 818e13c2760SPrzemyslaw Czarnowski const std::string& service, const std::string& name, 819988fb7b2SAdrian Ambrożewicz const std::string& imageUrl, const bool rw, 820988fb7b2SAdrian Ambrożewicz std::string&& userName, std::string&& password) 821e13c2760SPrzemyslaw Czarnowski { 822988fb7b2SAdrian Ambrożewicz using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>; 823988fb7b2SAdrian Ambrożewicz constexpr const size_t secretLimit = 1024; 824988fb7b2SAdrian Ambrożewicz 825988fb7b2SAdrian Ambrożewicz std::shared_ptr<SecurePipe> secretPipe; 826988fb7b2SAdrian Ambrożewicz std::variant<int, SecurePipe::unix_fd> unixFd = -1; 827988fb7b2SAdrian Ambrożewicz 828988fb7b2SAdrian Ambrożewicz if (!userName.empty() || !password.empty()) 829988fb7b2SAdrian Ambrożewicz { 830988fb7b2SAdrian Ambrożewicz // Encapsulate in safe buffer 831988fb7b2SAdrian Ambrożewicz CredentialsProvider credentials(std::move(userName), 832988fb7b2SAdrian Ambrożewicz std::move(password)); 833988fb7b2SAdrian Ambrożewicz 834988fb7b2SAdrian Ambrożewicz // Payload must contain data + NULL delimiters 835988fb7b2SAdrian Ambrożewicz if (credentials.user().size() + credentials.password().size() + 2 > 836988fb7b2SAdrian Ambrożewicz secretLimit) 837988fb7b2SAdrian Ambrożewicz { 838988fb7b2SAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Credentials too long to handle"; 839988fb7b2SAdrian Ambrożewicz messages::unrecognizedRequestBody(asyncResp->res); 840988fb7b2SAdrian Ambrożewicz return; 841988fb7b2SAdrian Ambrożewicz } 842988fb7b2SAdrian Ambrożewicz 843988fb7b2SAdrian Ambrożewicz // Pack secret 844988fb7b2SAdrian Ambrożewicz auto secret = credentials.pack([](const auto& user, 845988fb7b2SAdrian Ambrożewicz const auto& pass, auto& buff) { 846988fb7b2SAdrian Ambrożewicz std::copy(user.begin(), user.end(), std::back_inserter(buff)); 847988fb7b2SAdrian Ambrożewicz buff.push_back('\0'); 848988fb7b2SAdrian Ambrożewicz std::copy(pass.begin(), pass.end(), std::back_inserter(buff)); 849988fb7b2SAdrian Ambrożewicz buff.push_back('\0'); 850988fb7b2SAdrian Ambrożewicz }); 851988fb7b2SAdrian Ambrożewicz 852988fb7b2SAdrian Ambrożewicz // Open pipe 853988fb7b2SAdrian Ambrożewicz secretPipe = std::make_shared<SecurePipe>( 854988fb7b2SAdrian Ambrożewicz crow::connections::systemBus->get_io_context(), 855988fb7b2SAdrian Ambrożewicz std::move(secret)); 856988fb7b2SAdrian Ambrożewicz unixFd = secretPipe->fd(); 857988fb7b2SAdrian Ambrożewicz 858988fb7b2SAdrian Ambrożewicz // Pass secret over pipe 85981ce609eSEd Tanous secretPipe->asyncWrite( 860f5b16f03SVikram Bodireddy [asyncResp](const boost::system::error_code& ec, std::size_t) { 861988fb7b2SAdrian Ambrożewicz if (ec) 862988fb7b2SAdrian Ambrożewicz { 863988fb7b2SAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec; 864988fb7b2SAdrian Ambrożewicz messages::internalError(asyncResp->res); 865988fb7b2SAdrian Ambrożewicz } 866988fb7b2SAdrian Ambrożewicz }); 867988fb7b2SAdrian Ambrożewicz } 868988fb7b2SAdrian Ambrożewicz 869e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 870988fb7b2SAdrian Ambrożewicz [asyncResp, secretPipe](const boost::system::error_code ec, 871988fb7b2SAdrian Ambrożewicz bool success) { 872e13c2760SPrzemyslaw Czarnowski if (ec) 873e13c2760SPrzemyslaw Czarnowski { 874e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 875e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 876d6da5bebSAdrian Ambrożewicz } 877d6da5bebSAdrian Ambrożewicz else if (!success) 878d6da5bebSAdrian Ambrożewicz { 879d6da5bebSAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Service responded with error"; 880d6da5bebSAdrian Ambrożewicz messages::generalError(asyncResp->res); 881e13c2760SPrzemyslaw Czarnowski } 882e13c2760SPrzemyslaw Czarnowski }, 883e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, 884988fb7b2SAdrian Ambrożewicz "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw, 885988fb7b2SAdrian Ambrożewicz unixFd); 886e13c2760SPrzemyslaw Czarnowski } 887e13c2760SPrzemyslaw Czarnowski }; 888e13c2760SPrzemyslaw Czarnowski 889e13c2760SPrzemyslaw Czarnowski /** 890e13c2760SPrzemyslaw Czarnowski @brief EjectMedia action class 891e13c2760SPrzemyslaw Czarnowski */ 892e13c2760SPrzemyslaw Czarnowski class VirtualMediaActionEjectMedia : public Node 893e13c2760SPrzemyslaw Czarnowski { 894e13c2760SPrzemyslaw Czarnowski public: 89552cc112dSEd Tanous VirtualMediaActionEjectMedia(App& app) : 896e13c2760SPrzemyslaw Czarnowski Node(app, 897e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/" 898e13c2760SPrzemyslaw Czarnowski "VirtualMedia.EjectMedia", 899e13c2760SPrzemyslaw Czarnowski std::string(), std::string()) 900e13c2760SPrzemyslaw Czarnowski { 901e13c2760SPrzemyslaw Czarnowski entityPrivileges = { 902e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 903e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 904e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 905e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 906e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 907e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 908e13c2760SPrzemyslaw Czarnowski } 909e13c2760SPrzemyslaw Czarnowski 910e13c2760SPrzemyslaw Czarnowski private: 911e13c2760SPrzemyslaw Czarnowski /** 912e13c2760SPrzemyslaw Czarnowski * @brief Function handles POST method request. 913e13c2760SPrzemyslaw Czarnowski * 914e13c2760SPrzemyslaw Czarnowski * Analyzes POST body message before sends Reset request data to dbus. 915e13c2760SPrzemyslaw Czarnowski */ 9168d1b46d7Szhanghch05 void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9178d1b46d7Szhanghch05 const crow::Request& req, 918e13c2760SPrzemyslaw Czarnowski const std::vector<std::string>& params) override 919e13c2760SPrzemyslaw Czarnowski { 920e13c2760SPrzemyslaw Czarnowski if (params.size() != 2) 921e13c2760SPrzemyslaw Czarnowski { 9228d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 923e13c2760SPrzemyslaw Czarnowski return; 924e13c2760SPrzemyslaw Czarnowski } 925e13c2760SPrzemyslaw Czarnowski 926e13c2760SPrzemyslaw Czarnowski // take resource name from URL 927e13c2760SPrzemyslaw Czarnowski const std::string& resName = params[1]; 928e13c2760SPrzemyslaw Czarnowski 929e13c2760SPrzemyslaw Czarnowski if (params[0] != "bmc") 930e13c2760SPrzemyslaw Czarnowski { 9318d1b46d7Szhanghch05 messages::resourceNotFound(asyncResp->res, "VirtualMedia.Eject", 9328d1b46d7Szhanghch05 resName); 933e13c2760SPrzemyslaw Czarnowski 934e13c2760SPrzemyslaw Czarnowski return; 935e13c2760SPrzemyslaw Czarnowski } 936e13c2760SPrzemyslaw Czarnowski 937e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 9388d1b46d7Szhanghch05 [this, asyncResp{std::move(asyncResp)}, req, 939e13c2760SPrzemyslaw Czarnowski resName](const boost::system::error_code ec, 940e13c2760SPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 941e13c2760SPrzemyslaw Czarnowski if (ec) 942e13c2760SPrzemyslaw Czarnowski { 943e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 944e13c2760SPrzemyslaw Czarnowski << ec; 9458d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 946e13c2760SPrzemyslaw Czarnowski 947e13c2760SPrzemyslaw Czarnowski return; 948e13c2760SPrzemyslaw Czarnowski } 949e13c2760SPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 950e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 951e13c2760SPrzemyslaw Czarnowski 952e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 95381ce609eSEd Tanous [this, resName, service, req, 9548d1b46d7Szhanghch05 asyncResp{asyncResp}](const boost::system::error_code ec, 955e13c2760SPrzemyslaw Czarnowski ManagedObjectType& subtree) { 956e13c2760SPrzemyslaw Czarnowski if (ec) 957e13c2760SPrzemyslaw Czarnowski { 958e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 959e13c2760SPrzemyslaw Czarnowski 960e13c2760SPrzemyslaw Czarnowski return; 961e13c2760SPrzemyslaw Czarnowski } 962e13c2760SPrzemyslaw Czarnowski 963e13c2760SPrzemyslaw Czarnowski for (const auto& object : subtree) 964e13c2760SPrzemyslaw Czarnowski { 965e13c2760SPrzemyslaw Czarnowski const std::string& path = 966e13c2760SPrzemyslaw Czarnowski static_cast<const std::string&>(object.first); 967e13c2760SPrzemyslaw Czarnowski 968f23b7296SEd Tanous std::size_t lastIndex = path.rfind('/'); 969e13c2760SPrzemyslaw Czarnowski if (lastIndex == std::string::npos) 970e13c2760SPrzemyslaw Czarnowski { 971e13c2760SPrzemyslaw Czarnowski continue; 972e13c2760SPrzemyslaw Czarnowski } 973e13c2760SPrzemyslaw Czarnowski 974e13c2760SPrzemyslaw Czarnowski lastIndex += 1; 975e13c2760SPrzemyslaw Czarnowski 976e13c2760SPrzemyslaw Czarnowski if (path.substr(lastIndex) == resName) 977e13c2760SPrzemyslaw Czarnowski { 978e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Proxy"); 979e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 980e13c2760SPrzemyslaw Czarnowski { 981e13c2760SPrzemyslaw Czarnowski // Proxy mode 9828d1b46d7Szhanghch05 doVmAction(asyncResp, service, resName, 9838d1b46d7Szhanghch05 false); 984e13c2760SPrzemyslaw Czarnowski } 985e13c2760SPrzemyslaw Czarnowski 986e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Legacy"); 987e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 988e13c2760SPrzemyslaw Czarnowski { 989e13c2760SPrzemyslaw Czarnowski // Legacy mode 9908d1b46d7Szhanghch05 doVmAction(asyncResp, service, resName, 9918d1b46d7Szhanghch05 true); 992e13c2760SPrzemyslaw Czarnowski } 993e13c2760SPrzemyslaw Czarnowski 994e13c2760SPrzemyslaw Czarnowski return; 995e13c2760SPrzemyslaw Czarnowski } 996e13c2760SPrzemyslaw Czarnowski } 997e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Parent item not found"; 9988d1b46d7Szhanghch05 messages::resourceNotFound(asyncResp->res, 9998d1b46d7Szhanghch05 "VirtualMedia", resName); 1000e13c2760SPrzemyslaw Czarnowski }, 1001e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 1002e13c2760SPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 1003e13c2760SPrzemyslaw Czarnowski }, 1004e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 1005e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 1006e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 1007e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 1008e13c2760SPrzemyslaw Czarnowski } 1009e13c2760SPrzemyslaw Czarnowski 1010e13c2760SPrzemyslaw Czarnowski /** 1011e13c2760SPrzemyslaw Czarnowski * @brief Function transceives data with dbus directly. 1012e13c2760SPrzemyslaw Czarnowski * 1013e13c2760SPrzemyslaw Czarnowski * All BMC state properties will be retrieved before sending reset request. 1014e13c2760SPrzemyslaw Czarnowski */ 10158d1b46d7Szhanghch05 void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1016e13c2760SPrzemyslaw Czarnowski const std::string& service, const std::string& name, 1017e13c2760SPrzemyslaw Czarnowski bool legacy) 1018e13c2760SPrzemyslaw Czarnowski { 1019e13c2760SPrzemyslaw Czarnowski 1020e13c2760SPrzemyslaw Czarnowski // Legacy mount requires parameter with image 1021e13c2760SPrzemyslaw Czarnowski if (legacy) 1022e13c2760SPrzemyslaw Czarnowski { 1023e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1024e13c2760SPrzemyslaw Czarnowski [asyncResp](const boost::system::error_code ec) { 1025e13c2760SPrzemyslaw Czarnowski if (ec) 1026e13c2760SPrzemyslaw Czarnowski { 1027e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 1028e13c2760SPrzemyslaw Czarnowski 1029e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1030e13c2760SPrzemyslaw Czarnowski return; 1031e13c2760SPrzemyslaw Czarnowski } 1032e13c2760SPrzemyslaw Czarnowski }, 1033e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, 1034e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount"); 1035e13c2760SPrzemyslaw Czarnowski } 1036e13c2760SPrzemyslaw Czarnowski else // proxy 1037e13c2760SPrzemyslaw Czarnowski { 1038e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1039e13c2760SPrzemyslaw Czarnowski [asyncResp](const boost::system::error_code ec) { 1040e13c2760SPrzemyslaw Czarnowski if (ec) 1041e13c2760SPrzemyslaw Czarnowski { 1042e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 1043e13c2760SPrzemyslaw Czarnowski 1044e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1045e13c2760SPrzemyslaw Czarnowski return; 1046e13c2760SPrzemyslaw Czarnowski } 1047e13c2760SPrzemyslaw Czarnowski }, 1048e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name, 1049e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount"); 1050e13c2760SPrzemyslaw Czarnowski } 1051e13c2760SPrzemyslaw Czarnowski } 1052e13c2760SPrzemyslaw Czarnowski }; 1053e13c2760SPrzemyslaw Czarnowski 1054107077deSPrzemyslaw Czarnowski class VirtualMediaCollection : public Node 1055107077deSPrzemyslaw Czarnowski { 1056107077deSPrzemyslaw Czarnowski public: 1057107077deSPrzemyslaw Czarnowski /* 1058107077deSPrzemyslaw Czarnowski * Default Constructor 1059107077deSPrzemyslaw Czarnowski */ 106052cc112dSEd Tanous VirtualMediaCollection(App& app) : 1061107077deSPrzemyslaw Czarnowski Node(app, "/redfish/v1/Managers/<str>/VirtualMedia/", std::string()) 1062107077deSPrzemyslaw Czarnowski { 1063107077deSPrzemyslaw Czarnowski entityPrivileges = { 1064107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 1065107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 1066107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 1067107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 1068107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 1069107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 1070107077deSPrzemyslaw Czarnowski } 1071107077deSPrzemyslaw Czarnowski 1072107077deSPrzemyslaw Czarnowski private: 1073107077deSPrzemyslaw Czarnowski /** 1074107077deSPrzemyslaw Czarnowski * Functions triggers appropriate requests on DBus 1075107077deSPrzemyslaw Czarnowski */ 10768d1b46d7Szhanghch05 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10778d1b46d7Szhanghch05 const crow::Request&, 1078107077deSPrzemyslaw Czarnowski const std::vector<std::string>& params) override 1079107077deSPrzemyslaw Czarnowski { 1080107077deSPrzemyslaw Czarnowski 1081107077deSPrzemyslaw Czarnowski // Check if there is required param, truly entering this shall be 1082107077deSPrzemyslaw Czarnowski // impossible 1083107077deSPrzemyslaw Czarnowski if (params.size() != 1) 1084107077deSPrzemyslaw Czarnowski { 10858d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 1086107077deSPrzemyslaw Czarnowski 1087107077deSPrzemyslaw Czarnowski return; 1088107077deSPrzemyslaw Czarnowski } 1089107077deSPrzemyslaw Czarnowski 1090107077deSPrzemyslaw Czarnowski const std::string& name = params[0]; 1091107077deSPrzemyslaw Czarnowski 1092107077deSPrzemyslaw Czarnowski if (name != "bmc") 1093107077deSPrzemyslaw Czarnowski { 1094107077deSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, "VirtualMedia", name); 1095107077deSPrzemyslaw Czarnowski 1096107077deSPrzemyslaw Czarnowski return; 1097107077deSPrzemyslaw Czarnowski } 1098107077deSPrzemyslaw Czarnowski 10998d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1100107077deSPrzemyslaw Czarnowski "#VirtualMediaCollection.VirtualMediaCollection"; 11018d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Virtual Media Services"; 11028d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = 1103d6c414f3SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia"; 1104107077deSPrzemyslaw Czarnowski 1105107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1106107077deSPrzemyslaw Czarnowski [asyncResp, name](const boost::system::error_code ec, 1107107077deSPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 1108107077deSPrzemyslaw Czarnowski if (ec) 1109107077deSPrzemyslaw Czarnowski { 1110107077deSPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 1111107077deSPrzemyslaw Czarnowski << ec; 1112107077deSPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1113107077deSPrzemyslaw Czarnowski 1114107077deSPrzemyslaw Czarnowski return; 1115107077deSPrzemyslaw Czarnowski } 1116107077deSPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 1117107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 1118107077deSPrzemyslaw Czarnowski 1119107077deSPrzemyslaw Czarnowski getVmResourceList(asyncResp, service, name); 1120107077deSPrzemyslaw Czarnowski }, 1121107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 1122107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 1123107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 1124107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 1125107077deSPrzemyslaw Czarnowski } 1126107077deSPrzemyslaw Czarnowski }; 1127107077deSPrzemyslaw Czarnowski 1128107077deSPrzemyslaw Czarnowski class VirtualMedia : public Node 1129107077deSPrzemyslaw Czarnowski { 1130107077deSPrzemyslaw Czarnowski public: 1131107077deSPrzemyslaw Czarnowski /* 1132107077deSPrzemyslaw Czarnowski * Default Constructor 1133107077deSPrzemyslaw Czarnowski */ 113452cc112dSEd Tanous VirtualMedia(App& app) : 1135107077deSPrzemyslaw Czarnowski Node(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/", 1136107077deSPrzemyslaw Czarnowski std::string(), std::string()) 1137107077deSPrzemyslaw Czarnowski { 1138107077deSPrzemyslaw Czarnowski entityPrivileges = { 1139107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 1140107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 1141107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 1142107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 1143107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 1144107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 1145107077deSPrzemyslaw Czarnowski } 1146107077deSPrzemyslaw Czarnowski 1147107077deSPrzemyslaw Czarnowski private: 1148107077deSPrzemyslaw Czarnowski /** 1149107077deSPrzemyslaw Czarnowski * Functions triggers appropriate requests on DBus 1150107077deSPrzemyslaw Czarnowski */ 11518d1b46d7Szhanghch05 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11528d1b46d7Szhanghch05 const crow::Request&, 1153107077deSPrzemyslaw Czarnowski const std::vector<std::string>& params) override 1154107077deSPrzemyslaw Czarnowski { 1155107077deSPrzemyslaw Czarnowski // Check if there is required param, truly entering this shall be 1156107077deSPrzemyslaw Czarnowski // impossible 1157107077deSPrzemyslaw Czarnowski if (params.size() != 2) 1158107077deSPrzemyslaw Czarnowski { 11598d1b46d7Szhanghch05 messages::internalError(asyncResp->res); 1160107077deSPrzemyslaw Czarnowski return; 1161107077deSPrzemyslaw Czarnowski } 1162107077deSPrzemyslaw Czarnowski const std::string& name = params[0]; 1163107077deSPrzemyslaw Czarnowski const std::string& resName = params[1]; 1164107077deSPrzemyslaw Czarnowski 1165107077deSPrzemyslaw Czarnowski if (name != "bmc") 1166107077deSPrzemyslaw Czarnowski { 1167107077deSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName); 1168107077deSPrzemyslaw Czarnowski 1169107077deSPrzemyslaw Czarnowski return; 1170107077deSPrzemyslaw Czarnowski } 1171107077deSPrzemyslaw Czarnowski 1172107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1173107077deSPrzemyslaw Czarnowski [asyncResp, name, resName](const boost::system::error_code ec, 1174107077deSPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 1175107077deSPrzemyslaw Czarnowski if (ec) 1176107077deSPrzemyslaw Czarnowski { 1177107077deSPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 1178107077deSPrzemyslaw Czarnowski << ec; 1179107077deSPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1180107077deSPrzemyslaw Czarnowski 1181107077deSPrzemyslaw Czarnowski return; 1182107077deSPrzemyslaw Czarnowski } 1183107077deSPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 1184107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 1185107077deSPrzemyslaw Czarnowski 1186107077deSPrzemyslaw Czarnowski getVmData(asyncResp, service, name, resName); 1187107077deSPrzemyslaw Czarnowski }, 1188107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 1189107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 1190107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 1191107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 1192107077deSPrzemyslaw Czarnowski } 1193107077deSPrzemyslaw Czarnowski }; 1194107077deSPrzemyslaw Czarnowski 1195107077deSPrzemyslaw Czarnowski } // namespace redfish 1196