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> 25107077deSPrzemyslaw Czarnowski 26107077deSPrzemyslaw Czarnowski namespace redfish 27107077deSPrzemyslaw Czarnowski 28107077deSPrzemyslaw Czarnowski { 29107077deSPrzemyslaw Czarnowski 30107077deSPrzemyslaw Czarnowski /** 31107077deSPrzemyslaw Czarnowski * @brief Read all known properties from VM object interfaces 32107077deSPrzemyslaw Czarnowski */ 33107077deSPrzemyslaw Czarnowski static void vmParseInterfaceObject(const DbusInterfaceType& interface, 34107077deSPrzemyslaw Czarnowski std::shared_ptr<AsyncResp> aResp) 35107077deSPrzemyslaw Czarnowski { 36107077deSPrzemyslaw Czarnowski const auto mountPointIface = 37107077deSPrzemyslaw Czarnowski interface.find("xyz.openbmc_project.VirtualMedia.MountPoint"); 38107077deSPrzemyslaw Czarnowski if (mountPointIface == interface.cend()) 39107077deSPrzemyslaw Czarnowski { 40107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Interface MountPoint not found"; 41107077deSPrzemyslaw Czarnowski return; 42107077deSPrzemyslaw Czarnowski } 43107077deSPrzemyslaw Czarnowski 44107077deSPrzemyslaw Czarnowski const auto processIface = 45107077deSPrzemyslaw Czarnowski interface.find("xyz.openbmc_project.VirtualMedia.Process"); 46107077deSPrzemyslaw Czarnowski if (processIface == interface.cend()) 47107077deSPrzemyslaw Czarnowski { 48107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Interface Process not found"; 49107077deSPrzemyslaw Czarnowski return; 50107077deSPrzemyslaw Czarnowski } 51107077deSPrzemyslaw Czarnowski 52107077deSPrzemyslaw Czarnowski const auto endpointIdProperty = mountPointIface->second.find("EndpointId"); 53107077deSPrzemyslaw Czarnowski if (endpointIdProperty == mountPointIface->second.cend()) 54107077deSPrzemyslaw Czarnowski { 55107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Property EndpointId not found"; 56107077deSPrzemyslaw Czarnowski return; 57107077deSPrzemyslaw Czarnowski } 58107077deSPrzemyslaw Czarnowski 59107077deSPrzemyslaw Czarnowski const auto activeProperty = processIface->second.find("Active"); 60107077deSPrzemyslaw Czarnowski if (activeProperty == processIface->second.cend()) 61107077deSPrzemyslaw Czarnowski { 62107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Property Active not found"; 63107077deSPrzemyslaw Czarnowski return; 64107077deSPrzemyslaw Czarnowski } 65107077deSPrzemyslaw Czarnowski 66107077deSPrzemyslaw Czarnowski const bool* activeValue = std::get_if<bool>(&activeProperty->second); 67107077deSPrzemyslaw Czarnowski if (!activeValue) 68107077deSPrzemyslaw Czarnowski { 69107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Value Active not found"; 70107077deSPrzemyslaw Czarnowski return; 71107077deSPrzemyslaw Czarnowski } 72107077deSPrzemyslaw Czarnowski 73107077deSPrzemyslaw Czarnowski const std::string* endpointIdValue = 74107077deSPrzemyslaw Czarnowski std::get_if<std::string>(&endpointIdProperty->second); 75107077deSPrzemyslaw Czarnowski if (endpointIdValue) 76107077deSPrzemyslaw Czarnowski { 77107077deSPrzemyslaw Czarnowski if (!endpointIdValue->empty()) 78107077deSPrzemyslaw Czarnowski { 79107077deSPrzemyslaw Czarnowski // Proxy mode 80d04ba325SPrzemyslaw Czarnowski aResp->res.jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] = 81d04ba325SPrzemyslaw Czarnowski *endpointIdValue; 82107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["TransferProtocolType"] = "OEM"; 83107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Inserted"] = *activeValue; 84107077deSPrzemyslaw Czarnowski if (*activeValue == true) 85107077deSPrzemyslaw Czarnowski { 86107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["ConnectedVia"] = "Applet"; 87107077deSPrzemyslaw Czarnowski } 88107077deSPrzemyslaw Czarnowski } 89107077deSPrzemyslaw Czarnowski else 90107077deSPrzemyslaw Czarnowski { 91107077deSPrzemyslaw Czarnowski // Legacy mode 92107077deSPrzemyslaw Czarnowski const auto imageUrlProperty = 93107077deSPrzemyslaw Czarnowski mountPointIface->second.find("ImageURL"); 94107077deSPrzemyslaw Czarnowski if (imageUrlProperty != processIface->second.cend()) 95107077deSPrzemyslaw Czarnowski { 96107077deSPrzemyslaw Czarnowski const std::string* imageUrlValue = 97107077deSPrzemyslaw Czarnowski std::get_if<std::string>(&imageUrlProperty->second); 98107077deSPrzemyslaw Czarnowski if (imageUrlValue && !imageUrlValue->empty()) 99107077deSPrzemyslaw Czarnowski { 100*da4784d8SPrzemyslaw Czarnowski std::filesystem::path filePath = *imageUrlValue; 101*da4784d8SPrzemyslaw Czarnowski if (!filePath.has_filename()) 102*da4784d8SPrzemyslaw Czarnowski { 103*da4784d8SPrzemyslaw Czarnowski // this will handle https share, which not necessarily 104*da4784d8SPrzemyslaw Czarnowski // has to have filename given. 105*da4784d8SPrzemyslaw Czarnowski aResp->res.jsonValue["ImageName"] = ""; 106*da4784d8SPrzemyslaw Czarnowski } 107*da4784d8SPrzemyslaw Czarnowski else 108*da4784d8SPrzemyslaw Czarnowski { 109*da4784d8SPrzemyslaw Czarnowski aResp->res.jsonValue["ImageName"] = filePath.filename(); 110*da4784d8SPrzemyslaw Czarnowski } 111*da4784d8SPrzemyslaw Czarnowski 112*da4784d8SPrzemyslaw Czarnowski aResp->res.jsonValue["Image"] = *imageUrlValue; 113107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Inserted"] = *activeValue; 114107077deSPrzemyslaw Czarnowski if (*activeValue == true) 115107077deSPrzemyslaw Czarnowski { 116107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["ConnectedVia"] = "URI"; 117107077deSPrzemyslaw Czarnowski } 118107077deSPrzemyslaw Czarnowski } 119107077deSPrzemyslaw Czarnowski } 120107077deSPrzemyslaw Czarnowski } 121107077deSPrzemyslaw Czarnowski } 122107077deSPrzemyslaw Czarnowski } 123107077deSPrzemyslaw Czarnowski 124107077deSPrzemyslaw Czarnowski /** 125107077deSPrzemyslaw Czarnowski * @brief Fill template for Virtual Media Item. 126107077deSPrzemyslaw Czarnowski */ 127107077deSPrzemyslaw Czarnowski static nlohmann::json vmItemTemplate(const std::string& name, 128107077deSPrzemyslaw Czarnowski const std::string& resName) 129107077deSPrzemyslaw Czarnowski { 130107077deSPrzemyslaw Czarnowski nlohmann::json item; 131107077deSPrzemyslaw Czarnowski item["@odata.id"] = 132107077deSPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + resName; 133d04ba325SPrzemyslaw Czarnowski item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia"; 134107077deSPrzemyslaw Czarnowski item["Name"] = "Virtual Removable Media"; 135107077deSPrzemyslaw Czarnowski item["Id"] = resName; 136107077deSPrzemyslaw Czarnowski item["WriteProtected"] = true; 137107077deSPrzemyslaw Czarnowski item["MediaTypes"] = {"CD", "USBStick"}; 138107077deSPrzemyslaw Czarnowski item["TransferMethod"] = "Stream"; 139d04ba325SPrzemyslaw Czarnowski item["Oem"]["OpenBMC"]["@odata.type"] = 140d04ba325SPrzemyslaw Czarnowski "#OemVirtualMedia.v1_0_0.VirtualMedia"; 141107077deSPrzemyslaw Czarnowski 142107077deSPrzemyslaw Czarnowski return item; 143107077deSPrzemyslaw Czarnowski } 144107077deSPrzemyslaw Czarnowski 145107077deSPrzemyslaw Czarnowski /** 146107077deSPrzemyslaw Czarnowski * @brief Fills collection data 147107077deSPrzemyslaw Czarnowski */ 148107077deSPrzemyslaw Czarnowski static void getVmResourceList(std::shared_ptr<AsyncResp> aResp, 149107077deSPrzemyslaw Czarnowski const std::string& service, 150107077deSPrzemyslaw Czarnowski const std::string& name) 151107077deSPrzemyslaw Czarnowski { 152107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Get available Virtual Media resources."; 153107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 154107077deSPrzemyslaw Czarnowski [name, aResp{std::move(aResp)}](const boost::system::error_code ec, 155107077deSPrzemyslaw Czarnowski ManagedObjectType& subtree) { 156107077deSPrzemyslaw Czarnowski if (ec) 157107077deSPrzemyslaw Czarnowski { 158107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 159107077deSPrzemyslaw Czarnowski return; 160107077deSPrzemyslaw Czarnowski } 161107077deSPrzemyslaw Czarnowski nlohmann::json& members = aResp->res.jsonValue["Members"]; 162107077deSPrzemyslaw Czarnowski members = nlohmann::json::array(); 163107077deSPrzemyslaw Czarnowski 164107077deSPrzemyslaw Czarnowski for (const auto& object : subtree) 165107077deSPrzemyslaw Czarnowski { 166107077deSPrzemyslaw Czarnowski nlohmann::json item; 167107077deSPrzemyslaw Czarnowski const std::string& path = 168107077deSPrzemyslaw Czarnowski static_cast<const std::string&>(object.first); 169f23b7296SEd Tanous std::size_t lastIndex = path.rfind('/'); 170107077deSPrzemyslaw Czarnowski if (lastIndex == std::string::npos) 171107077deSPrzemyslaw Czarnowski { 172107077deSPrzemyslaw Czarnowski continue; 173107077deSPrzemyslaw Czarnowski } 174107077deSPrzemyslaw Czarnowski 175107077deSPrzemyslaw Czarnowski lastIndex += 1; 176107077deSPrzemyslaw Czarnowski 177107077deSPrzemyslaw Czarnowski item["@odata.id"] = "/redfish/v1/Managers/" + name + 178107077deSPrzemyslaw Czarnowski "/VirtualMedia/" + path.substr(lastIndex); 179107077deSPrzemyslaw Czarnowski 180107077deSPrzemyslaw Czarnowski members.emplace_back(std::move(item)); 181107077deSPrzemyslaw Czarnowski } 182107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Members@odata.count"] = members.size(); 183107077deSPrzemyslaw Czarnowski }, 184107077deSPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 185107077deSPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 186107077deSPrzemyslaw Czarnowski } 187107077deSPrzemyslaw Czarnowski 188107077deSPrzemyslaw Czarnowski /** 189107077deSPrzemyslaw Czarnowski * @brief Fills data for specific resource 190107077deSPrzemyslaw Czarnowski */ 191107077deSPrzemyslaw Czarnowski static void getVmData(std::shared_ptr<AsyncResp> aResp, 192107077deSPrzemyslaw Czarnowski const std::string& service, const std::string& name, 193107077deSPrzemyslaw Czarnowski const std::string& resName) 194107077deSPrzemyslaw Czarnowski { 195107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Get Virtual Media resource data."; 196107077deSPrzemyslaw Czarnowski 197107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 198107077deSPrzemyslaw Czarnowski [resName, name, aResp](const boost::system::error_code ec, 199107077deSPrzemyslaw Czarnowski ManagedObjectType& subtree) { 200107077deSPrzemyslaw Czarnowski if (ec) 201107077deSPrzemyslaw Czarnowski { 202107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 203e13c2760SPrzemyslaw Czarnowski 204107077deSPrzemyslaw Czarnowski return; 205107077deSPrzemyslaw Czarnowski } 206107077deSPrzemyslaw Czarnowski 207107077deSPrzemyslaw Czarnowski for (auto& item : subtree) 208107077deSPrzemyslaw Czarnowski { 209107077deSPrzemyslaw Czarnowski const std::string& path = 210107077deSPrzemyslaw Czarnowski static_cast<const std::string&>(item.first); 211107077deSPrzemyslaw Czarnowski 212f23b7296SEd Tanous std::size_t lastItem = path.rfind('/'); 213107077deSPrzemyslaw Czarnowski if (lastItem == std::string::npos) 214107077deSPrzemyslaw Czarnowski { 215107077deSPrzemyslaw Czarnowski continue; 216107077deSPrzemyslaw Czarnowski } 217107077deSPrzemyslaw Czarnowski 218107077deSPrzemyslaw Czarnowski if (path.substr(lastItem + 1) != resName) 219107077deSPrzemyslaw Czarnowski { 220107077deSPrzemyslaw Czarnowski continue; 221107077deSPrzemyslaw Czarnowski } 222107077deSPrzemyslaw Czarnowski 223107077deSPrzemyslaw Czarnowski aResp->res.jsonValue = vmItemTemplate(name, resName); 224107077deSPrzemyslaw Czarnowski 225e13c2760SPrzemyslaw Czarnowski // Check if dbus path is Legacy type 226e13c2760SPrzemyslaw Czarnowski if (path.find("VirtualMedia/Legacy") != std::string::npos) 227e13c2760SPrzemyslaw Czarnowski { 228e13c2760SPrzemyslaw Czarnowski aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"] 229e13c2760SPrzemyslaw Czarnowski ["target"] = 230e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + 231e13c2760SPrzemyslaw Czarnowski resName + "/Actions/VirtualMedia.InsertMedia"; 232e13c2760SPrzemyslaw Czarnowski } 233e13c2760SPrzemyslaw Czarnowski 234107077deSPrzemyslaw Czarnowski vmParseInterfaceObject(item.second, aResp); 235107077deSPrzemyslaw Czarnowski 236e13c2760SPrzemyslaw Czarnowski aResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"] 237e13c2760SPrzemyslaw Czarnowski ["target"] = 238e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + 239e13c2760SPrzemyslaw Czarnowski resName + "/Actions/VirtualMedia.EjectMedia"; 240e13c2760SPrzemyslaw Czarnowski 241107077deSPrzemyslaw Czarnowski return; 242107077deSPrzemyslaw Czarnowski } 243107077deSPrzemyslaw Czarnowski 244107077deSPrzemyslaw Czarnowski messages::resourceNotFound( 245d04ba325SPrzemyslaw Czarnowski aResp->res, "#VirtualMedia.v1_3_0.VirtualMedia", resName); 246107077deSPrzemyslaw Czarnowski }, 247107077deSPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 248107077deSPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 249107077deSPrzemyslaw Czarnowski } 250107077deSPrzemyslaw Czarnowski 251e13c2760SPrzemyslaw Czarnowski /** 252e13c2760SPrzemyslaw Czarnowski @brief InsertMedia action class 253e13c2760SPrzemyslaw Czarnowski */ 254e13c2760SPrzemyslaw Czarnowski class VirtualMediaActionInsertMedia : public Node 255e13c2760SPrzemyslaw Czarnowski { 256e13c2760SPrzemyslaw Czarnowski public: 25752cc112dSEd Tanous VirtualMediaActionInsertMedia(App& app) : 258e13c2760SPrzemyslaw Czarnowski Node(app, 259e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/" 260e13c2760SPrzemyslaw Czarnowski "VirtualMedia.InsertMedia", 261e13c2760SPrzemyslaw Czarnowski std::string(), std::string()) 262e13c2760SPrzemyslaw Czarnowski { 263e13c2760SPrzemyslaw Czarnowski entityPrivileges = { 264e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 265e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 266e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 267e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 268e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 269e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 270e13c2760SPrzemyslaw Czarnowski } 271e13c2760SPrzemyslaw Czarnowski 272e13c2760SPrzemyslaw Czarnowski private: 273e13c2760SPrzemyslaw Czarnowski /** 274c6f4e017SAgata Olender * @brief Transfer protocols supported for InsertMedia action. 275c6f4e017SAgata Olender * 276c6f4e017SAgata Olender */ 277c6f4e017SAgata Olender enum class TransferProtocol 278c6f4e017SAgata Olender { 279c6f4e017SAgata Olender https, 280c6f4e017SAgata Olender smb, 281c6f4e017SAgata Olender invalid 282c6f4e017SAgata Olender }; 283c6f4e017SAgata Olender 284c6f4e017SAgata Olender /** 285c6f4e017SAgata Olender * @brief Function extracts transfer protocol type from URI. 286c6f4e017SAgata Olender * 287c6f4e017SAgata Olender */ 288c6f4e017SAgata Olender std::optional<TransferProtocol> 289c6f4e017SAgata Olender getTransferProtocolFromUri(const std::string& imageUri) 290c6f4e017SAgata Olender { 291c6f4e017SAgata Olender if (imageUri.find("smb://") != std::string::npos) 292c6f4e017SAgata Olender { 293c6f4e017SAgata Olender return TransferProtocol::smb; 294c6f4e017SAgata Olender } 295c6f4e017SAgata Olender else if (imageUri.find("https://") != std::string::npos) 296c6f4e017SAgata Olender { 297c6f4e017SAgata Olender return TransferProtocol::https; 298c6f4e017SAgata Olender } 299c6f4e017SAgata Olender else if (imageUri.find("://") != std::string::npos) 300c6f4e017SAgata Olender { 301c6f4e017SAgata Olender return TransferProtocol::invalid; 302c6f4e017SAgata Olender } 303c6f4e017SAgata Olender else 304c6f4e017SAgata Olender { 305c6f4e017SAgata Olender return {}; 306c6f4e017SAgata Olender } 307c6f4e017SAgata Olender } 308c6f4e017SAgata Olender 309c6f4e017SAgata Olender /** 310c6f4e017SAgata Olender * @brief Function convert transfer protocol from string param. 311c6f4e017SAgata Olender * 312c6f4e017SAgata Olender */ 313c6f4e017SAgata Olender std::optional<TransferProtocol> getTransferProtocolFromParam( 314c6f4e017SAgata Olender const std::optional<std::string>& transferProtocolType) 315c6f4e017SAgata Olender { 316c6f4e017SAgata Olender if (transferProtocolType == std::nullopt) 317c6f4e017SAgata Olender { 318c6f4e017SAgata Olender return {}; 319c6f4e017SAgata Olender } 320c6f4e017SAgata Olender 321c6f4e017SAgata Olender if (*transferProtocolType == "CIFS") 322c6f4e017SAgata Olender { 323c6f4e017SAgata Olender return TransferProtocol::smb; 324c6f4e017SAgata Olender } 325c6f4e017SAgata Olender 326c6f4e017SAgata Olender if (*transferProtocolType == "HTTPS") 327c6f4e017SAgata Olender { 328c6f4e017SAgata Olender return TransferProtocol::https; 329c6f4e017SAgata Olender } 330c6f4e017SAgata Olender 331c6f4e017SAgata Olender return TransferProtocol::invalid; 332c6f4e017SAgata Olender } 333c6f4e017SAgata Olender 334c6f4e017SAgata Olender /** 335c6f4e017SAgata Olender * @brief Function extends URI with transfer protocol type. 336c6f4e017SAgata Olender * 337c6f4e017SAgata Olender */ 338c6f4e017SAgata Olender const std::string 339c6f4e017SAgata Olender getUriWithTransferProtocol(const std::string& imageUri, 340c6f4e017SAgata Olender const TransferProtocol& transferProtocol) 341c6f4e017SAgata Olender { 342c6f4e017SAgata Olender if (transferProtocol == TransferProtocol::smb) 343c6f4e017SAgata Olender { 344c6f4e017SAgata Olender return "smb://" + imageUri; 345c6f4e017SAgata Olender } 346c6f4e017SAgata Olender 347c6f4e017SAgata Olender if (transferProtocol == TransferProtocol::https) 348c6f4e017SAgata Olender { 349c6f4e017SAgata Olender return "https://" + imageUri; 350c6f4e017SAgata Olender } 351c6f4e017SAgata Olender 352c6f4e017SAgata Olender return imageUri; 353c6f4e017SAgata Olender } 354c6f4e017SAgata Olender 355c6f4e017SAgata Olender /** 356c6f4e017SAgata Olender * @brief Function validate parameters of insert media request. 357c6f4e017SAgata Olender * 358c6f4e017SAgata Olender */ 359c6f4e017SAgata Olender bool validateParams(crow::Response& res, std::string& imageUrl, 360c6f4e017SAgata Olender const std::optional<bool>& inserted, 361c6f4e017SAgata Olender const std::optional<std::string>& transferMethod, 362c6f4e017SAgata Olender const std::optional<std::string>& transferProtocolType) 363c6f4e017SAgata Olender { 364c6f4e017SAgata Olender BMCWEB_LOG_DEBUG << "Validation started"; 365c6f4e017SAgata Olender // required param imageUrl must not be empty 366c6f4e017SAgata Olender if (imageUrl.empty()) 367c6f4e017SAgata Olender { 368c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter Image is empty."; 369c6f4e017SAgata Olender 370c6f4e017SAgata Olender messages::propertyValueFormatError(res, "<empty>", "Image"); 371c6f4e017SAgata Olender 372c6f4e017SAgata Olender return false; 373c6f4e017SAgata Olender } 374c6f4e017SAgata Olender 375c6f4e017SAgata Olender // optional param inserted must be true 376c6f4e017SAgata Olender if ((inserted != std::nullopt) && (*inserted != true)) 377c6f4e017SAgata Olender { 378c6f4e017SAgata Olender BMCWEB_LOG_ERROR 379c6f4e017SAgata Olender << "Request action optional parameter Inserted must be true."; 380c6f4e017SAgata Olender 381c6f4e017SAgata Olender messages::actionParameterNotSupported(res, "Inserted", 382c6f4e017SAgata Olender "InsertMedia"); 383c6f4e017SAgata Olender 384c6f4e017SAgata Olender return false; 385c6f4e017SAgata Olender } 386c6f4e017SAgata Olender 387c6f4e017SAgata Olender // optional param transferMethod must be stream 388c6f4e017SAgata Olender if ((transferMethod != std::nullopt) && (*transferMethod != "Stream")) 389c6f4e017SAgata Olender { 390c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action optional parameter " 391c6f4e017SAgata Olender "TransferMethod must be Stream."; 392c6f4e017SAgata Olender 393c6f4e017SAgata Olender messages::actionParameterNotSupported(res, "TransferMethod", 394c6f4e017SAgata Olender "InsertMedia"); 395c6f4e017SAgata Olender 396c6f4e017SAgata Olender return false; 397c6f4e017SAgata Olender } 398c6f4e017SAgata Olender 399c6f4e017SAgata Olender std::optional<TransferProtocol> uriTransferProtocolType = 400c6f4e017SAgata Olender getTransferProtocolFromUri(imageUrl); 401c6f4e017SAgata Olender 402c6f4e017SAgata Olender std::optional<TransferProtocol> paramTransferProtocolType = 403c6f4e017SAgata Olender getTransferProtocolFromParam(transferProtocolType); 404c6f4e017SAgata Olender 405c6f4e017SAgata Olender // ImageUrl does not contain valid protocol type 406c6f4e017SAgata Olender if (*uriTransferProtocolType == TransferProtocol::invalid) 407c6f4e017SAgata Olender { 408c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must " 409c6f4e017SAgata Olender "contain specified protocol type from list: " 410c6f4e017SAgata Olender "(smb, https)."; 411c6f4e017SAgata Olender 412c6f4e017SAgata Olender messages::resourceAtUriInUnknownFormat(res, imageUrl); 413c6f4e017SAgata Olender 414c6f4e017SAgata Olender return false; 415c6f4e017SAgata Olender } 416c6f4e017SAgata Olender 417c6f4e017SAgata Olender // transferProtocolType should contain value from list 418c6f4e017SAgata Olender if (*paramTransferProtocolType == TransferProtocol::invalid) 419c6f4e017SAgata Olender { 420c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType " 421c6f4e017SAgata Olender "must be provided with value from list: " 422c6f4e017SAgata Olender "(CIFS, HTTPS)."; 423c6f4e017SAgata Olender 424c6f4e017SAgata Olender messages::propertyValueNotInList(res, *transferProtocolType, 425c6f4e017SAgata Olender "TransferProtocolType"); 426c6f4e017SAgata Olender return false; 427c6f4e017SAgata Olender } 428c6f4e017SAgata Olender 429c6f4e017SAgata Olender // valid transfer protocol not provided either with URI nor param 430c6f4e017SAgata Olender if ((uriTransferProtocolType == std::nullopt) && 431c6f4e017SAgata Olender (paramTransferProtocolType == std::nullopt)) 432c6f4e017SAgata Olender { 433c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must " 434c6f4e017SAgata Olender "contain specified protocol type or param " 435c6f4e017SAgata Olender "TransferProtocolType must be provided."; 436c6f4e017SAgata Olender 437c6f4e017SAgata Olender messages::resourceAtUriInUnknownFormat(res, imageUrl); 438c6f4e017SAgata Olender 439c6f4e017SAgata Olender return false; 440c6f4e017SAgata Olender } 441c6f4e017SAgata Olender 442c6f4e017SAgata Olender // valid transfer protocol provided both with URI and param 443c6f4e017SAgata Olender if ((paramTransferProtocolType != std::nullopt) && 444c6f4e017SAgata Olender (uriTransferProtocolType != std::nullopt)) 445c6f4e017SAgata Olender { 446c6f4e017SAgata Olender // check if protocol is the same for URI and param 447c6f4e017SAgata Olender if (*paramTransferProtocolType != *uriTransferProtocolType) 448c6f4e017SAgata Olender { 449c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter " 450c6f4e017SAgata Olender "TransferProtocolType must contain the " 451c6f4e017SAgata Olender "same protocol type as protocol type " 452c6f4e017SAgata Olender "provided with param imageUrl."; 453c6f4e017SAgata Olender 454c6f4e017SAgata Olender messages::actionParameterValueTypeError( 455c6f4e017SAgata Olender res, *transferProtocolType, "TransferProtocolType", 456c6f4e017SAgata Olender "InsertMedia"); 457c6f4e017SAgata Olender 458c6f4e017SAgata Olender return false; 459c6f4e017SAgata Olender } 460c6f4e017SAgata Olender } 461c6f4e017SAgata Olender 462c6f4e017SAgata Olender // validation passed 463c6f4e017SAgata Olender // add protocol to URI if needed 464c6f4e017SAgata Olender if (uriTransferProtocolType == std::nullopt) 465c6f4e017SAgata Olender { 466c6f4e017SAgata Olender imageUrl = getUriWithTransferProtocol(imageUrl, 467c6f4e017SAgata Olender *paramTransferProtocolType); 468c6f4e017SAgata Olender } 469c6f4e017SAgata Olender 470c6f4e017SAgata Olender return true; 471c6f4e017SAgata Olender } 472c6f4e017SAgata Olender 473c6f4e017SAgata Olender /** 474e13c2760SPrzemyslaw Czarnowski * @brief Function handles POST method request. 475e13c2760SPrzemyslaw Czarnowski * 476e13c2760SPrzemyslaw Czarnowski * Analyzes POST body message before sends Reset request data to dbus. 477e13c2760SPrzemyslaw Czarnowski */ 478e13c2760SPrzemyslaw Czarnowski void doPost(crow::Response& res, const crow::Request& req, 479e13c2760SPrzemyslaw Czarnowski const std::vector<std::string>& params) override 480e13c2760SPrzemyslaw Czarnowski { 481e13c2760SPrzemyslaw Czarnowski auto aResp = std::make_shared<AsyncResp>(res); 482e13c2760SPrzemyslaw Czarnowski 483e13c2760SPrzemyslaw Czarnowski if (params.size() != 2) 484e13c2760SPrzemyslaw Czarnowski { 485e13c2760SPrzemyslaw Czarnowski messages::internalError(res); 486e13c2760SPrzemyslaw Czarnowski return; 487e13c2760SPrzemyslaw Czarnowski } 488e13c2760SPrzemyslaw Czarnowski 489e13c2760SPrzemyslaw Czarnowski // take resource name from URL 490e13c2760SPrzemyslaw Czarnowski const std::string& resName = params[1]; 491e13c2760SPrzemyslaw Czarnowski 492e13c2760SPrzemyslaw Czarnowski if (params[0] != "bmc") 493e13c2760SPrzemyslaw Czarnowski { 494e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound(res, "VirtualMedia.Insert", resName); 495e13c2760SPrzemyslaw Czarnowski 496e13c2760SPrzemyslaw Czarnowski return; 497e13c2760SPrzemyslaw Czarnowski } 498e13c2760SPrzemyslaw Czarnowski 499e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 500e13c2760SPrzemyslaw Czarnowski [this, aResp{std::move(aResp)}, req, 501e13c2760SPrzemyslaw Czarnowski resName](const boost::system::error_code ec, 502e13c2760SPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 503e13c2760SPrzemyslaw Czarnowski if (ec) 504e13c2760SPrzemyslaw Czarnowski { 505e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 506e13c2760SPrzemyslaw Czarnowski << ec; 507e13c2760SPrzemyslaw Czarnowski messages::internalError(aResp->res); 508e13c2760SPrzemyslaw Czarnowski 509e13c2760SPrzemyslaw Czarnowski return; 510e13c2760SPrzemyslaw Czarnowski } 511e13c2760SPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 512e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 513e13c2760SPrzemyslaw Czarnowski 514e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 515e13c2760SPrzemyslaw Czarnowski [this, service, resName, req, aResp{std::move(aResp)}]( 516e13c2760SPrzemyslaw Czarnowski const boost::system::error_code ec, 517e13c2760SPrzemyslaw Czarnowski ManagedObjectType& subtree) { 518e13c2760SPrzemyslaw Czarnowski if (ec) 519e13c2760SPrzemyslaw Czarnowski { 520e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 521e13c2760SPrzemyslaw Czarnowski 522e13c2760SPrzemyslaw Czarnowski return; 523e13c2760SPrzemyslaw Czarnowski } 524e13c2760SPrzemyslaw Czarnowski 525e13c2760SPrzemyslaw Czarnowski for (const auto& object : subtree) 526e13c2760SPrzemyslaw Czarnowski { 527e13c2760SPrzemyslaw Czarnowski const std::string& path = 528e13c2760SPrzemyslaw Czarnowski static_cast<const std::string&>(object.first); 529e13c2760SPrzemyslaw Czarnowski 530f23b7296SEd Tanous std::size_t lastIndex = path.rfind('/'); 531e13c2760SPrzemyslaw Czarnowski if (lastIndex == std::string::npos) 532e13c2760SPrzemyslaw Czarnowski { 533e13c2760SPrzemyslaw Czarnowski continue; 534e13c2760SPrzemyslaw Czarnowski } 535e13c2760SPrzemyslaw Czarnowski 536e13c2760SPrzemyslaw Czarnowski lastIndex += 1; 537e13c2760SPrzemyslaw Czarnowski 538e13c2760SPrzemyslaw Czarnowski if (path.substr(lastIndex) == resName) 539e13c2760SPrzemyslaw Czarnowski { 540e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Proxy"); 541e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 542e13c2760SPrzemyslaw Czarnowski { 543e13c2760SPrzemyslaw Czarnowski // Not possible in proxy mode 544e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "InsertMedia not " 545e13c2760SPrzemyslaw Czarnowski "allowed in proxy mode"; 546e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound( 547e13c2760SPrzemyslaw Czarnowski aResp->res, "VirtualMedia.InsertMedia", 548e13c2760SPrzemyslaw Czarnowski resName); 549e13c2760SPrzemyslaw Czarnowski 550e13c2760SPrzemyslaw Czarnowski return; 551e13c2760SPrzemyslaw Czarnowski } 552e13c2760SPrzemyslaw Czarnowski 553e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Legacy"); 554c6f4e017SAgata Olender if (lastIndex == std::string::npos) 555e13c2760SPrzemyslaw Czarnowski { 556c6f4e017SAgata Olender continue; 557c6f4e017SAgata Olender } 558c6f4e017SAgata Olender 559e13c2760SPrzemyslaw Czarnowski // Legacy mode 560e13c2760SPrzemyslaw Czarnowski std::string imageUrl; 561c6f4e017SAgata Olender std::optional<std::string> userName; 562c6f4e017SAgata Olender std::optional<std::string> password; 563c6f4e017SAgata Olender std::optional<std::string> transferMethod; 564c6f4e017SAgata Olender std::optional<std::string> transferProtocolType; 565c6f4e017SAgata Olender std::optional<bool> writeProtected = true; 566c6f4e017SAgata Olender std::optional<bool> inserted; 567e13c2760SPrzemyslaw Czarnowski 5684e0453b1SGunnar Mills // Read obligatory parameters (url of image) 569d6da5bebSAdrian Ambrożewicz if (!json_util::readJson( 570d6da5bebSAdrian Ambrożewicz req, aResp->res, "Image", imageUrl, 571988fb7b2SAdrian Ambrożewicz "WriteProtected", writeProtected, 572988fb7b2SAdrian Ambrożewicz "UserName", userName, "Password", 573c6f4e017SAgata Olender password, "Inserted", inserted, 574c6f4e017SAgata Olender "TransferMethod", transferMethod, 575c6f4e017SAgata Olender "TransferProtocolType", 576c6f4e017SAgata Olender transferProtocolType)) 577e13c2760SPrzemyslaw Czarnowski { 578c6f4e017SAgata Olender BMCWEB_LOG_DEBUG << "Image is not provided"; 579e13c2760SPrzemyslaw Czarnowski return; 580e13c2760SPrzemyslaw Czarnowski } 581e13c2760SPrzemyslaw Czarnowski 582c6f4e017SAgata Olender bool paramsValid = validateParams( 583c6f4e017SAgata Olender aResp->res, imageUrl, inserted, 584c6f4e017SAgata Olender transferMethod, transferProtocolType); 585c6f4e017SAgata Olender 586c6f4e017SAgata Olender if (paramsValid == false) 587e13c2760SPrzemyslaw Czarnowski { 588e13c2760SPrzemyslaw Czarnowski return; 589e13c2760SPrzemyslaw Czarnowski } 590e13c2760SPrzemyslaw Czarnowski 591c6f4e017SAgata Olender // manager is irrelevant for VirtualMedia dbus 592c6f4e017SAgata Olender // calls 593c6f4e017SAgata Olender doMountVmLegacy( 594c6f4e017SAgata Olender std::move(aResp), service, resName, 595c6f4e017SAgata Olender imageUrl, !(*writeProtected), 596c6f4e017SAgata Olender std::move(*userName), std::move(*password)); 597e13c2760SPrzemyslaw Czarnowski 598e13c2760SPrzemyslaw Czarnowski return; 599e13c2760SPrzemyslaw Czarnowski } 600e13c2760SPrzemyslaw Czarnowski } 601e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Parent item not found"; 602e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound(aResp->res, "VirtualMedia", 603e13c2760SPrzemyslaw Czarnowski resName); 604e13c2760SPrzemyslaw Czarnowski }, 605e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 606e13c2760SPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 607e13c2760SPrzemyslaw Czarnowski }, 608e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 609e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 610e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 611e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 612e13c2760SPrzemyslaw Czarnowski } 613e13c2760SPrzemyslaw Czarnowski 6141214b7e7SGunnar Mills template <typename T> 6151214b7e7SGunnar Mills static void secureCleanup(T& value) 616988fb7b2SAdrian Ambrożewicz { 617988fb7b2SAdrian Ambrożewicz auto raw = const_cast<typename T::value_type*>(value.data()); 618988fb7b2SAdrian Ambrożewicz explicit_bzero(raw, value.size() * sizeof(*raw)); 619988fb7b2SAdrian Ambrożewicz } 620988fb7b2SAdrian Ambrożewicz 621988fb7b2SAdrian Ambrożewicz class Credentials 622988fb7b2SAdrian Ambrożewicz { 623988fb7b2SAdrian Ambrożewicz public: 624988fb7b2SAdrian Ambrożewicz Credentials(std::string&& user, std::string&& password) : 625988fb7b2SAdrian Ambrożewicz userBuf(std::move(user)), passBuf(std::move(password)) 6261214b7e7SGunnar Mills {} 627988fb7b2SAdrian Ambrożewicz 628988fb7b2SAdrian Ambrożewicz ~Credentials() 629988fb7b2SAdrian Ambrożewicz { 630988fb7b2SAdrian Ambrożewicz secureCleanup(userBuf); 631988fb7b2SAdrian Ambrożewicz secureCleanup(passBuf); 632988fb7b2SAdrian Ambrożewicz } 633988fb7b2SAdrian Ambrożewicz 634988fb7b2SAdrian Ambrożewicz const std::string& user() 635988fb7b2SAdrian Ambrożewicz { 636988fb7b2SAdrian Ambrożewicz return userBuf; 637988fb7b2SAdrian Ambrożewicz } 638988fb7b2SAdrian Ambrożewicz 639988fb7b2SAdrian Ambrożewicz const std::string& password() 640988fb7b2SAdrian Ambrożewicz { 641988fb7b2SAdrian Ambrożewicz return passBuf; 642988fb7b2SAdrian Ambrożewicz } 643988fb7b2SAdrian Ambrożewicz 644988fb7b2SAdrian Ambrożewicz private: 645988fb7b2SAdrian Ambrożewicz Credentials() = delete; 646988fb7b2SAdrian Ambrożewicz Credentials(const Credentials&) = delete; 647988fb7b2SAdrian Ambrożewicz Credentials& operator=(const Credentials&) = delete; 648988fb7b2SAdrian Ambrożewicz 649988fb7b2SAdrian Ambrożewicz std::string userBuf; 650988fb7b2SAdrian Ambrożewicz std::string passBuf; 651988fb7b2SAdrian Ambrożewicz }; 652988fb7b2SAdrian Ambrożewicz 653988fb7b2SAdrian Ambrożewicz class CredentialsProvider 654988fb7b2SAdrian Ambrożewicz { 655988fb7b2SAdrian Ambrożewicz public: 6561214b7e7SGunnar Mills template <typename T> 6571214b7e7SGunnar Mills struct Deleter 658988fb7b2SAdrian Ambrożewicz { 659988fb7b2SAdrian Ambrożewicz void operator()(T* buff) const 660988fb7b2SAdrian Ambrożewicz { 661988fb7b2SAdrian Ambrożewicz if (buff) 662988fb7b2SAdrian Ambrożewicz { 663988fb7b2SAdrian Ambrożewicz secureCleanup(*buff); 664988fb7b2SAdrian Ambrożewicz delete buff; 665988fb7b2SAdrian Ambrożewicz } 666988fb7b2SAdrian Ambrożewicz } 667988fb7b2SAdrian Ambrożewicz }; 668988fb7b2SAdrian Ambrożewicz 669988fb7b2SAdrian Ambrożewicz using Buffer = std::vector<char>; 670988fb7b2SAdrian Ambrożewicz using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>; 671988fb7b2SAdrian Ambrożewicz // Using explicit definition instead of std::function to avoid implicit 672988fb7b2SAdrian Ambrożewicz // conversions eg. stack copy instead of reference 673988fb7b2SAdrian Ambrożewicz using FormatterFunc = void(const std::string& username, 674988fb7b2SAdrian Ambrożewicz const std::string& password, Buffer& dest); 675988fb7b2SAdrian Ambrożewicz 676988fb7b2SAdrian Ambrożewicz CredentialsProvider(std::string&& user, std::string&& password) : 677988fb7b2SAdrian Ambrożewicz credentials(std::move(user), std::move(password)) 6781214b7e7SGunnar Mills {} 679988fb7b2SAdrian Ambrożewicz 680988fb7b2SAdrian Ambrożewicz const std::string& user() 681988fb7b2SAdrian Ambrożewicz { 682988fb7b2SAdrian Ambrożewicz return credentials.user(); 683988fb7b2SAdrian Ambrożewicz } 684988fb7b2SAdrian Ambrożewicz 685988fb7b2SAdrian Ambrożewicz const std::string& password() 686988fb7b2SAdrian Ambrożewicz { 687988fb7b2SAdrian Ambrożewicz return credentials.password(); 688988fb7b2SAdrian Ambrożewicz } 689988fb7b2SAdrian Ambrożewicz 690988fb7b2SAdrian Ambrożewicz SecureBuffer pack(const FormatterFunc formatter) 691988fb7b2SAdrian Ambrożewicz { 692988fb7b2SAdrian Ambrożewicz SecureBuffer packed{new Buffer{}}; 693988fb7b2SAdrian Ambrożewicz if (formatter) 694988fb7b2SAdrian Ambrożewicz { 695988fb7b2SAdrian Ambrożewicz formatter(credentials.user(), credentials.password(), *packed); 696988fb7b2SAdrian Ambrożewicz } 697988fb7b2SAdrian Ambrożewicz 698988fb7b2SAdrian Ambrożewicz return packed; 699988fb7b2SAdrian Ambrożewicz } 700988fb7b2SAdrian Ambrożewicz 701988fb7b2SAdrian Ambrożewicz private: 702988fb7b2SAdrian Ambrożewicz Credentials credentials; 703988fb7b2SAdrian Ambrożewicz }; 704988fb7b2SAdrian Ambrożewicz 705988fb7b2SAdrian Ambrożewicz // Wrapper for boost::async_pipe ensuring proper pipe cleanup 7061214b7e7SGunnar Mills template <typename Buffer> 7071214b7e7SGunnar Mills class Pipe 708988fb7b2SAdrian Ambrożewicz { 709988fb7b2SAdrian Ambrożewicz public: 710988fb7b2SAdrian Ambrożewicz using unix_fd = sdbusplus::message::unix_fd; 711988fb7b2SAdrian Ambrożewicz 712988fb7b2SAdrian Ambrożewicz Pipe(boost::asio::io_context& io, Buffer&& buffer) : 713988fb7b2SAdrian Ambrożewicz impl(io), buffer{std::move(buffer)} 7141214b7e7SGunnar Mills {} 715988fb7b2SAdrian Ambrożewicz 716988fb7b2SAdrian Ambrożewicz ~Pipe() 717988fb7b2SAdrian Ambrożewicz { 718988fb7b2SAdrian Ambrożewicz // Named pipe needs to be explicitly removed 719988fb7b2SAdrian Ambrożewicz impl.close(); 720988fb7b2SAdrian Ambrożewicz } 721988fb7b2SAdrian Ambrożewicz 722988fb7b2SAdrian Ambrożewicz unix_fd fd() 723988fb7b2SAdrian Ambrożewicz { 724988fb7b2SAdrian Ambrożewicz return unix_fd{impl.native_source()}; 725988fb7b2SAdrian Ambrożewicz } 726988fb7b2SAdrian Ambrożewicz 727988fb7b2SAdrian Ambrożewicz template <typename WriteHandler> 728988fb7b2SAdrian Ambrożewicz void async_write(WriteHandler&& handler) 729988fb7b2SAdrian Ambrożewicz { 730988fb7b2SAdrian Ambrożewicz impl.async_write_some(data(), std::forward<WriteHandler>(handler)); 731988fb7b2SAdrian Ambrożewicz } 732988fb7b2SAdrian Ambrożewicz 733988fb7b2SAdrian Ambrożewicz private: 734988fb7b2SAdrian Ambrożewicz // Specialization for pointer types 735988fb7b2SAdrian Ambrożewicz template <typename B = Buffer> 736988fb7b2SAdrian Ambrożewicz typename std::enable_if<boost::has_dereference<B>::value, 737988fb7b2SAdrian Ambrożewicz boost::asio::const_buffer>::type 738988fb7b2SAdrian Ambrożewicz data() 739988fb7b2SAdrian Ambrożewicz { 740988fb7b2SAdrian Ambrożewicz return boost::asio::buffer(*buffer); 741988fb7b2SAdrian Ambrożewicz } 742988fb7b2SAdrian Ambrożewicz 743988fb7b2SAdrian Ambrożewicz template <typename B = Buffer> 744988fb7b2SAdrian Ambrożewicz typename std::enable_if<!boost::has_dereference<B>::value, 745988fb7b2SAdrian Ambrożewicz boost::asio::const_buffer>::type 746988fb7b2SAdrian Ambrożewicz data() 747988fb7b2SAdrian Ambrożewicz { 748988fb7b2SAdrian Ambrożewicz return boost::asio::buffer(buffer); 749988fb7b2SAdrian Ambrożewicz } 750988fb7b2SAdrian Ambrożewicz 751988fb7b2SAdrian Ambrożewicz const std::string name; 752988fb7b2SAdrian Ambrożewicz boost::process::async_pipe impl; 753988fb7b2SAdrian Ambrożewicz Buffer buffer; 754988fb7b2SAdrian Ambrożewicz }; 755988fb7b2SAdrian Ambrożewicz 756e13c2760SPrzemyslaw Czarnowski /** 757e13c2760SPrzemyslaw Czarnowski * @brief Function transceives data with dbus directly. 758e13c2760SPrzemyslaw Czarnowski * 759e13c2760SPrzemyslaw Czarnowski * All BMC state properties will be retrieved before sending reset request. 760e13c2760SPrzemyslaw Czarnowski */ 761d6da5bebSAdrian Ambrożewicz void doMountVmLegacy(std::shared_ptr<AsyncResp> asyncResp, 762e13c2760SPrzemyslaw Czarnowski const std::string& service, const std::string& name, 763988fb7b2SAdrian Ambrożewicz const std::string& imageUrl, const bool rw, 764988fb7b2SAdrian Ambrożewicz std::string&& userName, std::string&& password) 765e13c2760SPrzemyslaw Czarnowski { 766988fb7b2SAdrian Ambrożewicz using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>; 767988fb7b2SAdrian Ambrożewicz constexpr const size_t secretLimit = 1024; 768988fb7b2SAdrian Ambrożewicz 769988fb7b2SAdrian Ambrożewicz std::shared_ptr<SecurePipe> secretPipe; 770988fb7b2SAdrian Ambrożewicz std::variant<int, SecurePipe::unix_fd> unixFd = -1; 771988fb7b2SAdrian Ambrożewicz 772988fb7b2SAdrian Ambrożewicz if (!userName.empty() || !password.empty()) 773988fb7b2SAdrian Ambrożewicz { 774988fb7b2SAdrian Ambrożewicz // Encapsulate in safe buffer 775988fb7b2SAdrian Ambrożewicz CredentialsProvider credentials(std::move(userName), 776988fb7b2SAdrian Ambrożewicz std::move(password)); 777988fb7b2SAdrian Ambrożewicz 778988fb7b2SAdrian Ambrożewicz // Payload must contain data + NULL delimiters 779988fb7b2SAdrian Ambrożewicz if (credentials.user().size() + credentials.password().size() + 2 > 780988fb7b2SAdrian Ambrożewicz secretLimit) 781988fb7b2SAdrian Ambrożewicz { 782988fb7b2SAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Credentials too long to handle"; 783988fb7b2SAdrian Ambrożewicz messages::unrecognizedRequestBody(asyncResp->res); 784988fb7b2SAdrian Ambrożewicz return; 785988fb7b2SAdrian Ambrożewicz } 786988fb7b2SAdrian Ambrożewicz 787988fb7b2SAdrian Ambrożewicz // Pack secret 788988fb7b2SAdrian Ambrożewicz auto secret = credentials.pack([](const auto& user, 789988fb7b2SAdrian Ambrożewicz const auto& pass, auto& buff) { 790988fb7b2SAdrian Ambrożewicz std::copy(user.begin(), user.end(), std::back_inserter(buff)); 791988fb7b2SAdrian Ambrożewicz buff.push_back('\0'); 792988fb7b2SAdrian Ambrożewicz std::copy(pass.begin(), pass.end(), std::back_inserter(buff)); 793988fb7b2SAdrian Ambrożewicz buff.push_back('\0'); 794988fb7b2SAdrian Ambrożewicz }); 795988fb7b2SAdrian Ambrożewicz 796988fb7b2SAdrian Ambrożewicz // Open pipe 797988fb7b2SAdrian Ambrożewicz secretPipe = std::make_shared<SecurePipe>( 798988fb7b2SAdrian Ambrożewicz crow::connections::systemBus->get_io_context(), 799988fb7b2SAdrian Ambrożewicz std::move(secret)); 800988fb7b2SAdrian Ambrożewicz unixFd = secretPipe->fd(); 801988fb7b2SAdrian Ambrożewicz 802988fb7b2SAdrian Ambrożewicz // Pass secret over pipe 803988fb7b2SAdrian Ambrożewicz secretPipe->async_write( 804f5b16f03SVikram Bodireddy [asyncResp](const boost::system::error_code& ec, std::size_t) { 805988fb7b2SAdrian Ambrożewicz if (ec) 806988fb7b2SAdrian Ambrożewicz { 807988fb7b2SAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec; 808988fb7b2SAdrian Ambrożewicz messages::internalError(asyncResp->res); 809988fb7b2SAdrian Ambrożewicz } 810988fb7b2SAdrian Ambrożewicz }); 811988fb7b2SAdrian Ambrożewicz } 812988fb7b2SAdrian Ambrożewicz 813e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 814988fb7b2SAdrian Ambrożewicz [asyncResp, secretPipe](const boost::system::error_code ec, 815988fb7b2SAdrian Ambrożewicz bool success) { 816e13c2760SPrzemyslaw Czarnowski if (ec) 817e13c2760SPrzemyslaw Czarnowski { 818e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 819e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 820d6da5bebSAdrian Ambrożewicz } 821d6da5bebSAdrian Ambrożewicz else if (!success) 822d6da5bebSAdrian Ambrożewicz { 823d6da5bebSAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Service responded with error"; 824d6da5bebSAdrian Ambrożewicz messages::generalError(asyncResp->res); 825e13c2760SPrzemyslaw Czarnowski } 826e13c2760SPrzemyslaw Czarnowski }, 827e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, 828988fb7b2SAdrian Ambrożewicz "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw, 829988fb7b2SAdrian Ambrożewicz unixFd); 830e13c2760SPrzemyslaw Czarnowski } 831e13c2760SPrzemyslaw Czarnowski }; 832e13c2760SPrzemyslaw Czarnowski 833e13c2760SPrzemyslaw Czarnowski /** 834e13c2760SPrzemyslaw Czarnowski @brief EjectMedia action class 835e13c2760SPrzemyslaw Czarnowski */ 836e13c2760SPrzemyslaw Czarnowski class VirtualMediaActionEjectMedia : public Node 837e13c2760SPrzemyslaw Czarnowski { 838e13c2760SPrzemyslaw Czarnowski public: 83952cc112dSEd Tanous VirtualMediaActionEjectMedia(App& app) : 840e13c2760SPrzemyslaw Czarnowski Node(app, 841e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/" 842e13c2760SPrzemyslaw Czarnowski "VirtualMedia.EjectMedia", 843e13c2760SPrzemyslaw Czarnowski std::string(), std::string()) 844e13c2760SPrzemyslaw Czarnowski { 845e13c2760SPrzemyslaw Czarnowski entityPrivileges = { 846e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 847e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 848e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 849e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 850e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 851e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 852e13c2760SPrzemyslaw Czarnowski } 853e13c2760SPrzemyslaw Czarnowski 854e13c2760SPrzemyslaw Czarnowski private: 855e13c2760SPrzemyslaw Czarnowski /** 856e13c2760SPrzemyslaw Czarnowski * @brief Function handles POST method request. 857e13c2760SPrzemyslaw Czarnowski * 858e13c2760SPrzemyslaw Czarnowski * Analyzes POST body message before sends Reset request data to dbus. 859e13c2760SPrzemyslaw Czarnowski */ 860e13c2760SPrzemyslaw Czarnowski void doPost(crow::Response& res, const crow::Request& req, 861e13c2760SPrzemyslaw Czarnowski const std::vector<std::string>& params) override 862e13c2760SPrzemyslaw Czarnowski { 863e13c2760SPrzemyslaw Czarnowski auto aResp = std::make_shared<AsyncResp>(res); 864e13c2760SPrzemyslaw Czarnowski 865e13c2760SPrzemyslaw Czarnowski if (params.size() != 2) 866e13c2760SPrzemyslaw Czarnowski { 867e13c2760SPrzemyslaw Czarnowski messages::internalError(res); 868e13c2760SPrzemyslaw Czarnowski return; 869e13c2760SPrzemyslaw Czarnowski } 870e13c2760SPrzemyslaw Czarnowski 871e13c2760SPrzemyslaw Czarnowski // take resource name from URL 872e13c2760SPrzemyslaw Czarnowski const std::string& resName = params[1]; 873e13c2760SPrzemyslaw Czarnowski 874e13c2760SPrzemyslaw Czarnowski if (params[0] != "bmc") 875e13c2760SPrzemyslaw Czarnowski { 876e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound(res, "VirtualMedia.Eject", resName); 877e13c2760SPrzemyslaw Czarnowski 878e13c2760SPrzemyslaw Czarnowski return; 879e13c2760SPrzemyslaw Czarnowski } 880e13c2760SPrzemyslaw Czarnowski 881e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 882e13c2760SPrzemyslaw Czarnowski [this, aResp{std::move(aResp)}, req, 883e13c2760SPrzemyslaw Czarnowski resName](const boost::system::error_code ec, 884e13c2760SPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 885e13c2760SPrzemyslaw Czarnowski if (ec) 886e13c2760SPrzemyslaw Czarnowski { 887e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 888e13c2760SPrzemyslaw Czarnowski << ec; 889e13c2760SPrzemyslaw Czarnowski messages::internalError(aResp->res); 890e13c2760SPrzemyslaw Czarnowski 891e13c2760SPrzemyslaw Czarnowski return; 892e13c2760SPrzemyslaw Czarnowski } 893e13c2760SPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 894e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 895e13c2760SPrzemyslaw Czarnowski 896e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 897e13c2760SPrzemyslaw Czarnowski [this, resName, service, req, aResp{std::move(aResp)}]( 898e13c2760SPrzemyslaw Czarnowski const boost::system::error_code ec, 899e13c2760SPrzemyslaw Czarnowski ManagedObjectType& subtree) { 900e13c2760SPrzemyslaw Czarnowski if (ec) 901e13c2760SPrzemyslaw Czarnowski { 902e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 903e13c2760SPrzemyslaw Czarnowski 904e13c2760SPrzemyslaw Czarnowski return; 905e13c2760SPrzemyslaw Czarnowski } 906e13c2760SPrzemyslaw Czarnowski 907e13c2760SPrzemyslaw Czarnowski for (const auto& object : subtree) 908e13c2760SPrzemyslaw Czarnowski { 909e13c2760SPrzemyslaw Czarnowski const std::string& path = 910e13c2760SPrzemyslaw Czarnowski static_cast<const std::string&>(object.first); 911e13c2760SPrzemyslaw Czarnowski 912f23b7296SEd Tanous std::size_t lastIndex = path.rfind('/'); 913e13c2760SPrzemyslaw Czarnowski if (lastIndex == std::string::npos) 914e13c2760SPrzemyslaw Czarnowski { 915e13c2760SPrzemyslaw Czarnowski continue; 916e13c2760SPrzemyslaw Czarnowski } 917e13c2760SPrzemyslaw Czarnowski 918e13c2760SPrzemyslaw Czarnowski lastIndex += 1; 919e13c2760SPrzemyslaw Czarnowski 920e13c2760SPrzemyslaw Czarnowski if (path.substr(lastIndex) == resName) 921e13c2760SPrzemyslaw Czarnowski { 922e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Proxy"); 923e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 924e13c2760SPrzemyslaw Czarnowski { 925e13c2760SPrzemyslaw Czarnowski // Proxy mode 926e13c2760SPrzemyslaw Czarnowski doVmAction(std::move(aResp), service, 927e13c2760SPrzemyslaw Czarnowski resName, false); 928e13c2760SPrzemyslaw Czarnowski } 929e13c2760SPrzemyslaw Czarnowski 930e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Legacy"); 931e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 932e13c2760SPrzemyslaw Czarnowski { 933e13c2760SPrzemyslaw Czarnowski // Legacy mode 934e13c2760SPrzemyslaw Czarnowski doVmAction(std::move(aResp), service, 935e13c2760SPrzemyslaw Czarnowski resName, true); 936e13c2760SPrzemyslaw Czarnowski } 937e13c2760SPrzemyslaw Czarnowski 938e13c2760SPrzemyslaw Czarnowski return; 939e13c2760SPrzemyslaw Czarnowski } 940e13c2760SPrzemyslaw Czarnowski } 941e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Parent item not found"; 942e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound(aResp->res, "VirtualMedia", 943e13c2760SPrzemyslaw Czarnowski resName); 944e13c2760SPrzemyslaw Czarnowski }, 945e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 946e13c2760SPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 947e13c2760SPrzemyslaw Czarnowski }, 948e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 949e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 950e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 951e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 952e13c2760SPrzemyslaw Czarnowski } 953e13c2760SPrzemyslaw Czarnowski 954e13c2760SPrzemyslaw Czarnowski /** 955e13c2760SPrzemyslaw Czarnowski * @brief Function transceives data with dbus directly. 956e13c2760SPrzemyslaw Czarnowski * 957e13c2760SPrzemyslaw Czarnowski * All BMC state properties will be retrieved before sending reset request. 958e13c2760SPrzemyslaw Czarnowski */ 959e13c2760SPrzemyslaw Czarnowski void doVmAction(std::shared_ptr<AsyncResp> asyncResp, 960e13c2760SPrzemyslaw Czarnowski const std::string& service, const std::string& name, 961e13c2760SPrzemyslaw Czarnowski bool legacy) 962e13c2760SPrzemyslaw Czarnowski { 963e13c2760SPrzemyslaw Czarnowski 964e13c2760SPrzemyslaw Czarnowski // Legacy mount requires parameter with image 965e13c2760SPrzemyslaw Czarnowski if (legacy) 966e13c2760SPrzemyslaw Czarnowski { 967e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 968e13c2760SPrzemyslaw Czarnowski [asyncResp](const boost::system::error_code ec) { 969e13c2760SPrzemyslaw Czarnowski if (ec) 970e13c2760SPrzemyslaw Czarnowski { 971e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 972e13c2760SPrzemyslaw Czarnowski 973e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 974e13c2760SPrzemyslaw Czarnowski return; 975e13c2760SPrzemyslaw Czarnowski } 976e13c2760SPrzemyslaw Czarnowski }, 977e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, 978e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount"); 979e13c2760SPrzemyslaw Czarnowski } 980e13c2760SPrzemyslaw Czarnowski else // proxy 981e13c2760SPrzemyslaw Czarnowski { 982e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 983e13c2760SPrzemyslaw Czarnowski [asyncResp](const boost::system::error_code ec) { 984e13c2760SPrzemyslaw Czarnowski if (ec) 985e13c2760SPrzemyslaw Czarnowski { 986e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 987e13c2760SPrzemyslaw Czarnowski 988e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 989e13c2760SPrzemyslaw Czarnowski return; 990e13c2760SPrzemyslaw Czarnowski } 991e13c2760SPrzemyslaw Czarnowski }, 992e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name, 993e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount"); 994e13c2760SPrzemyslaw Czarnowski } 995e13c2760SPrzemyslaw Czarnowski } 996e13c2760SPrzemyslaw Czarnowski }; 997e13c2760SPrzemyslaw Czarnowski 998107077deSPrzemyslaw Czarnowski class VirtualMediaCollection : public Node 999107077deSPrzemyslaw Czarnowski { 1000107077deSPrzemyslaw Czarnowski public: 1001107077deSPrzemyslaw Czarnowski /* 1002107077deSPrzemyslaw Czarnowski * Default Constructor 1003107077deSPrzemyslaw Czarnowski */ 100452cc112dSEd Tanous VirtualMediaCollection(App& app) : 1005107077deSPrzemyslaw Czarnowski Node(app, "/redfish/v1/Managers/<str>/VirtualMedia/", std::string()) 1006107077deSPrzemyslaw Czarnowski { 1007107077deSPrzemyslaw Czarnowski entityPrivileges = { 1008107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 1009107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 1010107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 1011107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 1012107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 1013107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 1014107077deSPrzemyslaw Czarnowski } 1015107077deSPrzemyslaw Czarnowski 1016107077deSPrzemyslaw Czarnowski private: 1017107077deSPrzemyslaw Czarnowski /** 1018107077deSPrzemyslaw Czarnowski * Functions triggers appropriate requests on DBus 1019107077deSPrzemyslaw Czarnowski */ 1020f5b16f03SVikram Bodireddy void doGet(crow::Response& res, const crow::Request&, 1021107077deSPrzemyslaw Czarnowski const std::vector<std::string>& params) override 1022107077deSPrzemyslaw Czarnowski { 1023107077deSPrzemyslaw Czarnowski auto asyncResp = std::make_shared<AsyncResp>(res); 1024107077deSPrzemyslaw Czarnowski 1025107077deSPrzemyslaw Czarnowski // Check if there is required param, truly entering this shall be 1026107077deSPrzemyslaw Czarnowski // impossible 1027107077deSPrzemyslaw Czarnowski if (params.size() != 1) 1028107077deSPrzemyslaw Czarnowski { 1029107077deSPrzemyslaw Czarnowski messages::internalError(res); 1030107077deSPrzemyslaw Czarnowski 1031107077deSPrzemyslaw Czarnowski return; 1032107077deSPrzemyslaw Czarnowski } 1033107077deSPrzemyslaw Czarnowski 1034107077deSPrzemyslaw Czarnowski const std::string& name = params[0]; 1035107077deSPrzemyslaw Czarnowski 1036107077deSPrzemyslaw Czarnowski if (name != "bmc") 1037107077deSPrzemyslaw Czarnowski { 1038107077deSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, "VirtualMedia", name); 1039107077deSPrzemyslaw Czarnowski 1040107077deSPrzemyslaw Czarnowski return; 1041107077deSPrzemyslaw Czarnowski } 1042107077deSPrzemyslaw Czarnowski 1043107077deSPrzemyslaw Czarnowski res.jsonValue["@odata.type"] = 1044107077deSPrzemyslaw Czarnowski "#VirtualMediaCollection.VirtualMediaCollection"; 1045107077deSPrzemyslaw Czarnowski res.jsonValue["Name"] = "Virtual Media Services"; 1046107077deSPrzemyslaw Czarnowski res.jsonValue["@odata.id"] = 1047d6c414f3SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia"; 1048107077deSPrzemyslaw Czarnowski 1049107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1050107077deSPrzemyslaw Czarnowski [asyncResp, name](const boost::system::error_code ec, 1051107077deSPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 1052107077deSPrzemyslaw Czarnowski if (ec) 1053107077deSPrzemyslaw Czarnowski { 1054107077deSPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 1055107077deSPrzemyslaw Czarnowski << ec; 1056107077deSPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1057107077deSPrzemyslaw Czarnowski 1058107077deSPrzemyslaw Czarnowski return; 1059107077deSPrzemyslaw Czarnowski } 1060107077deSPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 1061107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 1062107077deSPrzemyslaw Czarnowski 1063107077deSPrzemyslaw Czarnowski getVmResourceList(asyncResp, service, name); 1064107077deSPrzemyslaw Czarnowski }, 1065107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 1066107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 1067107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 1068107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 1069107077deSPrzemyslaw Czarnowski } 1070107077deSPrzemyslaw Czarnowski }; 1071107077deSPrzemyslaw Czarnowski 1072107077deSPrzemyslaw Czarnowski class VirtualMedia : public Node 1073107077deSPrzemyslaw Czarnowski { 1074107077deSPrzemyslaw Czarnowski public: 1075107077deSPrzemyslaw Czarnowski /* 1076107077deSPrzemyslaw Czarnowski * Default Constructor 1077107077deSPrzemyslaw Czarnowski */ 107852cc112dSEd Tanous VirtualMedia(App& app) : 1079107077deSPrzemyslaw Czarnowski Node(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/", 1080107077deSPrzemyslaw Czarnowski std::string(), std::string()) 1081107077deSPrzemyslaw Czarnowski { 1082107077deSPrzemyslaw Czarnowski entityPrivileges = { 1083107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 1084107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 1085107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 1086107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 1087107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 1088107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 1089107077deSPrzemyslaw Czarnowski } 1090107077deSPrzemyslaw Czarnowski 1091107077deSPrzemyslaw Czarnowski private: 1092107077deSPrzemyslaw Czarnowski /** 1093107077deSPrzemyslaw Czarnowski * Functions triggers appropriate requests on DBus 1094107077deSPrzemyslaw Czarnowski */ 1095f5b16f03SVikram Bodireddy void doGet(crow::Response& res, const crow::Request&, 1096107077deSPrzemyslaw Czarnowski const std::vector<std::string>& params) override 1097107077deSPrzemyslaw Czarnowski { 1098107077deSPrzemyslaw Czarnowski // Check if there is required param, truly entering this shall be 1099107077deSPrzemyslaw Czarnowski // impossible 1100107077deSPrzemyslaw Czarnowski if (params.size() != 2) 1101107077deSPrzemyslaw Czarnowski { 1102107077deSPrzemyslaw Czarnowski messages::internalError(res); 1103107077deSPrzemyslaw Czarnowski 1104107077deSPrzemyslaw Czarnowski res.end(); 1105107077deSPrzemyslaw Czarnowski return; 1106107077deSPrzemyslaw Czarnowski } 1107107077deSPrzemyslaw Czarnowski const std::string& name = params[0]; 1108107077deSPrzemyslaw Czarnowski const std::string& resName = params[1]; 1109107077deSPrzemyslaw Czarnowski 1110107077deSPrzemyslaw Czarnowski auto asyncResp = std::make_shared<AsyncResp>(res); 1111107077deSPrzemyslaw Czarnowski 1112107077deSPrzemyslaw Czarnowski if (name != "bmc") 1113107077deSPrzemyslaw Czarnowski { 1114107077deSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName); 1115107077deSPrzemyslaw Czarnowski 1116107077deSPrzemyslaw Czarnowski return; 1117107077deSPrzemyslaw Czarnowski } 1118107077deSPrzemyslaw Czarnowski 1119107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1120107077deSPrzemyslaw Czarnowski [asyncResp, name, resName](const boost::system::error_code ec, 1121107077deSPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 1122107077deSPrzemyslaw Czarnowski if (ec) 1123107077deSPrzemyslaw Czarnowski { 1124107077deSPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 1125107077deSPrzemyslaw Czarnowski << ec; 1126107077deSPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1127107077deSPrzemyslaw Czarnowski 1128107077deSPrzemyslaw Czarnowski return; 1129107077deSPrzemyslaw Czarnowski } 1130107077deSPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 1131107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 1132107077deSPrzemyslaw Czarnowski 1133107077deSPrzemyslaw Czarnowski getVmData(asyncResp, service, name, resName); 1134107077deSPrzemyslaw Czarnowski }, 1135107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 1136107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 1137107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 1138107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 1139107077deSPrzemyslaw Czarnowski } 1140107077deSPrzemyslaw Czarnowski }; 1141107077deSPrzemyslaw Czarnowski 1142107077deSPrzemyslaw Czarnowski } // namespace redfish 1143