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