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> 25*9e319cf0SAnna Platash #include <boost/url/url_view.hpp> 26107077deSPrzemyslaw Czarnowski 27107077deSPrzemyslaw Czarnowski namespace redfish 28107077deSPrzemyslaw Czarnowski 29107077deSPrzemyslaw Czarnowski { 30*9e319cf0SAnna Platash /** 31*9e319cf0SAnna Platash * @brief Function extracts transfer protocol name from URI. 32*9e319cf0SAnna Platash */ 33*9e319cf0SAnna Platash static std::string getTransferProtocolTypeFromUri(const std::string& imageUri) 34*9e319cf0SAnna Platash { 35*9e319cf0SAnna Platash try 36*9e319cf0SAnna Platash { 37*9e319cf0SAnna Platash std::string_view scheme = boost::urls::url_view(imageUri).scheme(); 38*9e319cf0SAnna Platash if (scheme == "smb") 39*9e319cf0SAnna Platash { 40*9e319cf0SAnna Platash return "CIFS"; 41*9e319cf0SAnna Platash } 42*9e319cf0SAnna Platash else if (scheme == "https") 43*9e319cf0SAnna Platash { 44*9e319cf0SAnna Platash return "HTTPS"; 45*9e319cf0SAnna Platash } 46*9e319cf0SAnna Platash } 47*9e319cf0SAnna Platash catch (std::exception& p) 48*9e319cf0SAnna Platash { 49*9e319cf0SAnna Platash BMCWEB_LOG_ERROR << p.what(); 50*9e319cf0SAnna Platash } 51*9e319cf0SAnna Platash return "None"; 52*9e319cf0SAnna Platash } 53107077deSPrzemyslaw Czarnowski 54107077deSPrzemyslaw Czarnowski /** 55107077deSPrzemyslaw Czarnowski * @brief Read all known properties from VM object interfaces 56107077deSPrzemyslaw Czarnowski */ 57107077deSPrzemyslaw Czarnowski static void vmParseInterfaceObject(const DbusInterfaceType& interface, 58107077deSPrzemyslaw Czarnowski std::shared_ptr<AsyncResp> aResp) 59107077deSPrzemyslaw Czarnowski { 60107077deSPrzemyslaw Czarnowski const auto mountPointIface = 61107077deSPrzemyslaw Czarnowski interface.find("xyz.openbmc_project.VirtualMedia.MountPoint"); 62107077deSPrzemyslaw Czarnowski if (mountPointIface == interface.cend()) 63107077deSPrzemyslaw Czarnowski { 64107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Interface MountPoint not found"; 65107077deSPrzemyslaw Czarnowski return; 66107077deSPrzemyslaw Czarnowski } 67107077deSPrzemyslaw Czarnowski 68107077deSPrzemyslaw Czarnowski const auto processIface = 69107077deSPrzemyslaw Czarnowski interface.find("xyz.openbmc_project.VirtualMedia.Process"); 70107077deSPrzemyslaw Czarnowski if (processIface == interface.cend()) 71107077deSPrzemyslaw Czarnowski { 72107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Interface Process not found"; 73107077deSPrzemyslaw Czarnowski return; 74107077deSPrzemyslaw Czarnowski } 75107077deSPrzemyslaw Czarnowski 76107077deSPrzemyslaw Czarnowski const auto endpointIdProperty = mountPointIface->second.find("EndpointId"); 77107077deSPrzemyslaw Czarnowski if (endpointIdProperty == mountPointIface->second.cend()) 78107077deSPrzemyslaw Czarnowski { 79107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Property EndpointId not found"; 80107077deSPrzemyslaw Czarnowski return; 81107077deSPrzemyslaw Czarnowski } 82107077deSPrzemyslaw Czarnowski 83107077deSPrzemyslaw Czarnowski const auto activeProperty = processIface->second.find("Active"); 84107077deSPrzemyslaw Czarnowski if (activeProperty == processIface->second.cend()) 85107077deSPrzemyslaw Czarnowski { 86107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Property Active not found"; 87107077deSPrzemyslaw Czarnowski return; 88107077deSPrzemyslaw Czarnowski } 89107077deSPrzemyslaw Czarnowski 90107077deSPrzemyslaw Czarnowski const bool* activeValue = std::get_if<bool>(&activeProperty->second); 91107077deSPrzemyslaw Czarnowski if (!activeValue) 92107077deSPrzemyslaw Czarnowski { 93107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Value Active not found"; 94107077deSPrzemyslaw Czarnowski return; 95107077deSPrzemyslaw Czarnowski } 96107077deSPrzemyslaw Czarnowski 97107077deSPrzemyslaw Czarnowski const std::string* endpointIdValue = 98107077deSPrzemyslaw Czarnowski std::get_if<std::string>(&endpointIdProperty->second); 99107077deSPrzemyslaw Czarnowski if (endpointIdValue) 100107077deSPrzemyslaw Czarnowski { 101107077deSPrzemyslaw Czarnowski if (!endpointIdValue->empty()) 102107077deSPrzemyslaw Czarnowski { 103107077deSPrzemyslaw Czarnowski // Proxy mode 104d04ba325SPrzemyslaw Czarnowski aResp->res.jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] = 105d04ba325SPrzemyslaw Czarnowski *endpointIdValue; 106107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["TransferProtocolType"] = "OEM"; 107107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Inserted"] = *activeValue; 108107077deSPrzemyslaw Czarnowski if (*activeValue == true) 109107077deSPrzemyslaw Czarnowski { 110107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["ConnectedVia"] = "Applet"; 111107077deSPrzemyslaw Czarnowski } 112107077deSPrzemyslaw Czarnowski } 113107077deSPrzemyslaw Czarnowski else 114107077deSPrzemyslaw Czarnowski { 115107077deSPrzemyslaw Czarnowski // Legacy mode 116*9e319cf0SAnna Platash for (const auto& property : mountPointIface->second) 117*9e319cf0SAnna Platash { 118*9e319cf0SAnna Platash if (property.first == "ImageURL") 119107077deSPrzemyslaw Czarnowski { 120107077deSPrzemyslaw Czarnowski const std::string* imageUrlValue = 121*9e319cf0SAnna Platash std::get_if<std::string>(&property.second); 122107077deSPrzemyslaw Czarnowski if (imageUrlValue && !imageUrlValue->empty()) 123107077deSPrzemyslaw Czarnowski { 124da4784d8SPrzemyslaw Czarnowski std::filesystem::path filePath = *imageUrlValue; 125da4784d8SPrzemyslaw Czarnowski if (!filePath.has_filename()) 126da4784d8SPrzemyslaw Czarnowski { 127*9e319cf0SAnna Platash // this will handle https share, which not 128*9e319cf0SAnna Platash // necessarily has to have filename given. 129da4784d8SPrzemyslaw Czarnowski aResp->res.jsonValue["ImageName"] = ""; 130da4784d8SPrzemyslaw Czarnowski } 131da4784d8SPrzemyslaw Czarnowski else 132da4784d8SPrzemyslaw Czarnowski { 133*9e319cf0SAnna Platash aResp->res.jsonValue["ImageName"] = 134*9e319cf0SAnna Platash filePath.filename(); 135da4784d8SPrzemyslaw Czarnowski } 136da4784d8SPrzemyslaw Czarnowski 137da4784d8SPrzemyslaw Czarnowski aResp->res.jsonValue["Image"] = *imageUrlValue; 138107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Inserted"] = *activeValue; 139*9e319cf0SAnna Platash aResp->res.jsonValue["TransferProtocolType"] = 140*9e319cf0SAnna Platash getTransferProtocolTypeFromUri(*imageUrlValue); 141*9e319cf0SAnna Platash 142107077deSPrzemyslaw Czarnowski if (*activeValue == true) 143107077deSPrzemyslaw Czarnowski { 144107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["ConnectedVia"] = "URI"; 145107077deSPrzemyslaw Czarnowski } 146107077deSPrzemyslaw Czarnowski } 147107077deSPrzemyslaw Czarnowski } 148*9e319cf0SAnna Platash else if (property.first == "WriteProtected") 149*9e319cf0SAnna Platash { 150*9e319cf0SAnna Platash const bool* writeProtectedValue = 151*9e319cf0SAnna Platash std::get_if<bool>(&property.second); 152*9e319cf0SAnna Platash if (writeProtectedValue) 153*9e319cf0SAnna Platash { 154*9e319cf0SAnna Platash aResp->res.jsonValue["WriteProtected"] = 155*9e319cf0SAnna Platash *writeProtectedValue; 156*9e319cf0SAnna Platash } 157*9e319cf0SAnna Platash } 158*9e319cf0SAnna Platash } 159107077deSPrzemyslaw Czarnowski } 160107077deSPrzemyslaw Czarnowski } 161107077deSPrzemyslaw Czarnowski } 162107077deSPrzemyslaw Czarnowski 163107077deSPrzemyslaw Czarnowski /** 164107077deSPrzemyslaw Czarnowski * @brief Fill template for Virtual Media Item. 165107077deSPrzemyslaw Czarnowski */ 166107077deSPrzemyslaw Czarnowski static nlohmann::json vmItemTemplate(const std::string& name, 167107077deSPrzemyslaw Czarnowski const std::string& resName) 168107077deSPrzemyslaw Czarnowski { 169107077deSPrzemyslaw Czarnowski nlohmann::json item; 170107077deSPrzemyslaw Czarnowski item["@odata.id"] = 171107077deSPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + resName; 172d04ba325SPrzemyslaw Czarnowski item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia"; 173107077deSPrzemyslaw Czarnowski item["Name"] = "Virtual Removable Media"; 174107077deSPrzemyslaw Czarnowski item["Id"] = resName; 175107077deSPrzemyslaw Czarnowski item["WriteProtected"] = true; 176107077deSPrzemyslaw Czarnowski item["MediaTypes"] = {"CD", "USBStick"}; 177107077deSPrzemyslaw Czarnowski item["TransferMethod"] = "Stream"; 178d04ba325SPrzemyslaw Czarnowski item["Oem"]["OpenBMC"]["@odata.type"] = 179d04ba325SPrzemyslaw Czarnowski "#OemVirtualMedia.v1_0_0.VirtualMedia"; 180107077deSPrzemyslaw Czarnowski 181107077deSPrzemyslaw Czarnowski return item; 182107077deSPrzemyslaw Czarnowski } 183107077deSPrzemyslaw Czarnowski 184107077deSPrzemyslaw Czarnowski /** 185107077deSPrzemyslaw Czarnowski * @brief Fills collection data 186107077deSPrzemyslaw Czarnowski */ 187107077deSPrzemyslaw Czarnowski static void getVmResourceList(std::shared_ptr<AsyncResp> aResp, 188107077deSPrzemyslaw Czarnowski const std::string& service, 189107077deSPrzemyslaw Czarnowski const std::string& name) 190107077deSPrzemyslaw Czarnowski { 191107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Get available Virtual Media resources."; 192107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 193107077deSPrzemyslaw Czarnowski [name, aResp{std::move(aResp)}](const boost::system::error_code ec, 194107077deSPrzemyslaw Czarnowski ManagedObjectType& subtree) { 195107077deSPrzemyslaw Czarnowski if (ec) 196107077deSPrzemyslaw Czarnowski { 197107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 198107077deSPrzemyslaw Czarnowski return; 199107077deSPrzemyslaw Czarnowski } 200107077deSPrzemyslaw Czarnowski nlohmann::json& members = aResp->res.jsonValue["Members"]; 201107077deSPrzemyslaw Czarnowski members = nlohmann::json::array(); 202107077deSPrzemyslaw Czarnowski 203107077deSPrzemyslaw Czarnowski for (const auto& object : subtree) 204107077deSPrzemyslaw Czarnowski { 205107077deSPrzemyslaw Czarnowski nlohmann::json item; 206107077deSPrzemyslaw Czarnowski const std::string& path = 207107077deSPrzemyslaw Czarnowski static_cast<const std::string&>(object.first); 208f23b7296SEd Tanous std::size_t lastIndex = path.rfind('/'); 209107077deSPrzemyslaw Czarnowski if (lastIndex == std::string::npos) 210107077deSPrzemyslaw Czarnowski { 211107077deSPrzemyslaw Czarnowski continue; 212107077deSPrzemyslaw Czarnowski } 213107077deSPrzemyslaw Czarnowski 214107077deSPrzemyslaw Czarnowski lastIndex += 1; 215107077deSPrzemyslaw Czarnowski 216107077deSPrzemyslaw Czarnowski item["@odata.id"] = "/redfish/v1/Managers/" + name + 217107077deSPrzemyslaw Czarnowski "/VirtualMedia/" + path.substr(lastIndex); 218107077deSPrzemyslaw Czarnowski 219107077deSPrzemyslaw Czarnowski members.emplace_back(std::move(item)); 220107077deSPrzemyslaw Czarnowski } 221107077deSPrzemyslaw Czarnowski aResp->res.jsonValue["Members@odata.count"] = members.size(); 222107077deSPrzemyslaw Czarnowski }, 223107077deSPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 224107077deSPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 225107077deSPrzemyslaw Czarnowski } 226107077deSPrzemyslaw Czarnowski 227107077deSPrzemyslaw Czarnowski /** 228107077deSPrzemyslaw Czarnowski * @brief Fills data for specific resource 229107077deSPrzemyslaw Czarnowski */ 230107077deSPrzemyslaw Czarnowski static void getVmData(std::shared_ptr<AsyncResp> aResp, 231107077deSPrzemyslaw Czarnowski const std::string& service, const std::string& name, 232107077deSPrzemyslaw Czarnowski const std::string& resName) 233107077deSPrzemyslaw Czarnowski { 234107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Get Virtual Media resource data."; 235107077deSPrzemyslaw Czarnowski 236107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 237107077deSPrzemyslaw Czarnowski [resName, name, aResp](const boost::system::error_code ec, 238107077deSPrzemyslaw Czarnowski ManagedObjectType& subtree) { 239107077deSPrzemyslaw Czarnowski if (ec) 240107077deSPrzemyslaw Czarnowski { 241107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 242e13c2760SPrzemyslaw Czarnowski 243107077deSPrzemyslaw Czarnowski return; 244107077deSPrzemyslaw Czarnowski } 245107077deSPrzemyslaw Czarnowski 246107077deSPrzemyslaw Czarnowski for (auto& item : subtree) 247107077deSPrzemyslaw Czarnowski { 248107077deSPrzemyslaw Czarnowski const std::string& path = 249107077deSPrzemyslaw Czarnowski static_cast<const std::string&>(item.first); 250107077deSPrzemyslaw Czarnowski 251f23b7296SEd Tanous std::size_t lastItem = path.rfind('/'); 252107077deSPrzemyslaw Czarnowski if (lastItem == std::string::npos) 253107077deSPrzemyslaw Czarnowski { 254107077deSPrzemyslaw Czarnowski continue; 255107077deSPrzemyslaw Czarnowski } 256107077deSPrzemyslaw Czarnowski 257107077deSPrzemyslaw Czarnowski if (path.substr(lastItem + 1) != resName) 258107077deSPrzemyslaw Czarnowski { 259107077deSPrzemyslaw Czarnowski continue; 260107077deSPrzemyslaw Czarnowski } 261107077deSPrzemyslaw Czarnowski 262107077deSPrzemyslaw Czarnowski aResp->res.jsonValue = vmItemTemplate(name, resName); 263107077deSPrzemyslaw Czarnowski 264e13c2760SPrzemyslaw Czarnowski // Check if dbus path is Legacy type 265e13c2760SPrzemyslaw Czarnowski if (path.find("VirtualMedia/Legacy") != std::string::npos) 266e13c2760SPrzemyslaw Czarnowski { 267e13c2760SPrzemyslaw Czarnowski aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"] 268e13c2760SPrzemyslaw Czarnowski ["target"] = 269e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + 270e13c2760SPrzemyslaw Czarnowski resName + "/Actions/VirtualMedia.InsertMedia"; 271e13c2760SPrzemyslaw Czarnowski } 272e13c2760SPrzemyslaw Czarnowski 273107077deSPrzemyslaw Czarnowski vmParseInterfaceObject(item.second, aResp); 274107077deSPrzemyslaw Czarnowski 275e13c2760SPrzemyslaw Czarnowski aResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"] 276e13c2760SPrzemyslaw Czarnowski ["target"] = 277e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia/" + 278e13c2760SPrzemyslaw Czarnowski resName + "/Actions/VirtualMedia.EjectMedia"; 279e13c2760SPrzemyslaw Czarnowski 280107077deSPrzemyslaw Czarnowski return; 281107077deSPrzemyslaw Czarnowski } 282107077deSPrzemyslaw Czarnowski 283107077deSPrzemyslaw Czarnowski messages::resourceNotFound( 284d04ba325SPrzemyslaw Czarnowski aResp->res, "#VirtualMedia.v1_3_0.VirtualMedia", resName); 285107077deSPrzemyslaw Czarnowski }, 286107077deSPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 287107077deSPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 288107077deSPrzemyslaw Czarnowski } 289107077deSPrzemyslaw Czarnowski 290e13c2760SPrzemyslaw Czarnowski /** 291e13c2760SPrzemyslaw Czarnowski @brief InsertMedia action class 292e13c2760SPrzemyslaw Czarnowski */ 293e13c2760SPrzemyslaw Czarnowski class VirtualMediaActionInsertMedia : public Node 294e13c2760SPrzemyslaw Czarnowski { 295e13c2760SPrzemyslaw Czarnowski public: 29652cc112dSEd Tanous VirtualMediaActionInsertMedia(App& app) : 297e13c2760SPrzemyslaw Czarnowski Node(app, 298e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/" 299e13c2760SPrzemyslaw Czarnowski "VirtualMedia.InsertMedia", 300e13c2760SPrzemyslaw Czarnowski std::string(), std::string()) 301e13c2760SPrzemyslaw Czarnowski { 302e13c2760SPrzemyslaw Czarnowski entityPrivileges = { 303e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 304e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 305e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 306e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 307e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 308e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 309e13c2760SPrzemyslaw Czarnowski } 310e13c2760SPrzemyslaw Czarnowski 311e13c2760SPrzemyslaw Czarnowski private: 312e13c2760SPrzemyslaw Czarnowski /** 313c6f4e017SAgata Olender * @brief Transfer protocols supported for InsertMedia action. 314c6f4e017SAgata Olender * 315c6f4e017SAgata Olender */ 316c6f4e017SAgata Olender enum class TransferProtocol 317c6f4e017SAgata Olender { 318c6f4e017SAgata Olender https, 319c6f4e017SAgata Olender smb, 320c6f4e017SAgata Olender invalid 321c6f4e017SAgata Olender }; 322c6f4e017SAgata Olender 323c6f4e017SAgata Olender /** 324c6f4e017SAgata Olender * @brief Function extracts transfer protocol type from URI. 325c6f4e017SAgata Olender * 326c6f4e017SAgata Olender */ 327c6f4e017SAgata Olender std::optional<TransferProtocol> 328c6f4e017SAgata Olender getTransferProtocolFromUri(const std::string& imageUri) 329c6f4e017SAgata Olender { 330*9e319cf0SAnna Platash try 331*9e319cf0SAnna Platash { 332*9e319cf0SAnna Platash std::string_view scheme = boost::urls::url_view(imageUri).scheme(); 333*9e319cf0SAnna Platash if (scheme == "smb") 334c6f4e017SAgata Olender { 335c6f4e017SAgata Olender return TransferProtocol::smb; 336c6f4e017SAgata Olender } 337*9e319cf0SAnna Platash else if (scheme == "https") 338c6f4e017SAgata Olender { 339c6f4e017SAgata Olender return TransferProtocol::https; 340c6f4e017SAgata Olender } 341*9e319cf0SAnna Platash else if (!scheme.empty()) 342c6f4e017SAgata Olender { 343c6f4e017SAgata Olender return TransferProtocol::invalid; 344c6f4e017SAgata Olender } 345c6f4e017SAgata Olender } 346*9e319cf0SAnna Platash catch (std::exception& p) 347*9e319cf0SAnna Platash { 348*9e319cf0SAnna Platash BMCWEB_LOG_ERROR << p.what(); 349*9e319cf0SAnna Platash } 350*9e319cf0SAnna Platash 351*9e319cf0SAnna Platash return {}; 352c6f4e017SAgata Olender } 353c6f4e017SAgata Olender 354c6f4e017SAgata Olender /** 355c6f4e017SAgata Olender * @brief Function convert transfer protocol from string param. 356c6f4e017SAgata Olender * 357c6f4e017SAgata Olender */ 358c6f4e017SAgata Olender std::optional<TransferProtocol> getTransferProtocolFromParam( 359c6f4e017SAgata Olender const std::optional<std::string>& transferProtocolType) 360c6f4e017SAgata Olender { 361c6f4e017SAgata Olender if (transferProtocolType == std::nullopt) 362c6f4e017SAgata Olender { 363c6f4e017SAgata Olender return {}; 364c6f4e017SAgata Olender } 365c6f4e017SAgata Olender 366c6f4e017SAgata Olender if (*transferProtocolType == "CIFS") 367c6f4e017SAgata Olender { 368c6f4e017SAgata Olender return TransferProtocol::smb; 369c6f4e017SAgata Olender } 370c6f4e017SAgata Olender 371c6f4e017SAgata Olender if (*transferProtocolType == "HTTPS") 372c6f4e017SAgata Olender { 373c6f4e017SAgata Olender return TransferProtocol::https; 374c6f4e017SAgata Olender } 375c6f4e017SAgata Olender 376c6f4e017SAgata Olender return TransferProtocol::invalid; 377c6f4e017SAgata Olender } 378c6f4e017SAgata Olender 379c6f4e017SAgata Olender /** 380c6f4e017SAgata Olender * @brief Function extends URI with transfer protocol type. 381c6f4e017SAgata Olender * 382c6f4e017SAgata Olender */ 383c6f4e017SAgata Olender const std::string 384c6f4e017SAgata Olender getUriWithTransferProtocol(const std::string& imageUri, 385c6f4e017SAgata Olender const TransferProtocol& transferProtocol) 386c6f4e017SAgata Olender { 387c6f4e017SAgata Olender if (transferProtocol == TransferProtocol::smb) 388c6f4e017SAgata Olender { 389c6f4e017SAgata Olender return "smb://" + imageUri; 390c6f4e017SAgata Olender } 391c6f4e017SAgata Olender 392c6f4e017SAgata Olender if (transferProtocol == TransferProtocol::https) 393c6f4e017SAgata Olender { 394c6f4e017SAgata Olender return "https://" + imageUri; 395c6f4e017SAgata Olender } 396c6f4e017SAgata Olender 397c6f4e017SAgata Olender return imageUri; 398c6f4e017SAgata Olender } 399c6f4e017SAgata Olender 400c6f4e017SAgata Olender /** 401c6f4e017SAgata Olender * @brief Function validate parameters of insert media request. 402c6f4e017SAgata Olender * 403c6f4e017SAgata Olender */ 404c6f4e017SAgata Olender bool validateParams(crow::Response& res, std::string& imageUrl, 405c6f4e017SAgata Olender const std::optional<bool>& inserted, 406c6f4e017SAgata Olender const std::optional<std::string>& transferMethod, 407c6f4e017SAgata Olender const std::optional<std::string>& transferProtocolType) 408c6f4e017SAgata Olender { 409c6f4e017SAgata Olender BMCWEB_LOG_DEBUG << "Validation started"; 410c6f4e017SAgata Olender // required param imageUrl must not be empty 411c6f4e017SAgata Olender if (imageUrl.empty()) 412c6f4e017SAgata Olender { 413c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter Image is empty."; 414c6f4e017SAgata Olender 415c6f4e017SAgata Olender messages::propertyValueFormatError(res, "<empty>", "Image"); 416c6f4e017SAgata Olender 417c6f4e017SAgata Olender return false; 418c6f4e017SAgata Olender } 419c6f4e017SAgata Olender 420c6f4e017SAgata Olender // optional param inserted must be true 421c6f4e017SAgata Olender if ((inserted != std::nullopt) && (*inserted != true)) 422c6f4e017SAgata Olender { 423c6f4e017SAgata Olender BMCWEB_LOG_ERROR 424c6f4e017SAgata Olender << "Request action optional parameter Inserted must be true."; 425c6f4e017SAgata Olender 426c6f4e017SAgata Olender messages::actionParameterNotSupported(res, "Inserted", 427c6f4e017SAgata Olender "InsertMedia"); 428c6f4e017SAgata Olender 429c6f4e017SAgata Olender return false; 430c6f4e017SAgata Olender } 431c6f4e017SAgata Olender 432c6f4e017SAgata Olender // optional param transferMethod must be stream 433c6f4e017SAgata Olender if ((transferMethod != std::nullopt) && (*transferMethod != "Stream")) 434c6f4e017SAgata Olender { 435c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action optional parameter " 436c6f4e017SAgata Olender "TransferMethod must be Stream."; 437c6f4e017SAgata Olender 438c6f4e017SAgata Olender messages::actionParameterNotSupported(res, "TransferMethod", 439c6f4e017SAgata Olender "InsertMedia"); 440c6f4e017SAgata Olender 441c6f4e017SAgata Olender return false; 442c6f4e017SAgata Olender } 443c6f4e017SAgata Olender 444c6f4e017SAgata Olender std::optional<TransferProtocol> uriTransferProtocolType = 445c6f4e017SAgata Olender getTransferProtocolFromUri(imageUrl); 446c6f4e017SAgata Olender 447c6f4e017SAgata Olender std::optional<TransferProtocol> paramTransferProtocolType = 448c6f4e017SAgata Olender getTransferProtocolFromParam(transferProtocolType); 449c6f4e017SAgata Olender 450c6f4e017SAgata Olender // ImageUrl does not contain valid protocol type 451c6f4e017SAgata Olender if (*uriTransferProtocolType == TransferProtocol::invalid) 452c6f4e017SAgata Olender { 453c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must " 454c6f4e017SAgata Olender "contain specified protocol type from list: " 455c6f4e017SAgata Olender "(smb, https)."; 456c6f4e017SAgata Olender 457c6f4e017SAgata Olender messages::resourceAtUriInUnknownFormat(res, imageUrl); 458c6f4e017SAgata Olender 459c6f4e017SAgata Olender return false; 460c6f4e017SAgata Olender } 461c6f4e017SAgata Olender 462c6f4e017SAgata Olender // transferProtocolType should contain value from list 463c6f4e017SAgata Olender if (*paramTransferProtocolType == TransferProtocol::invalid) 464c6f4e017SAgata Olender { 465c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType " 466c6f4e017SAgata Olender "must be provided with value from list: " 467c6f4e017SAgata Olender "(CIFS, HTTPS)."; 468c6f4e017SAgata Olender 469c6f4e017SAgata Olender messages::propertyValueNotInList(res, *transferProtocolType, 470c6f4e017SAgata Olender "TransferProtocolType"); 471c6f4e017SAgata Olender return false; 472c6f4e017SAgata Olender } 473c6f4e017SAgata Olender 474c6f4e017SAgata Olender // valid transfer protocol not provided either with URI nor param 475c6f4e017SAgata Olender if ((uriTransferProtocolType == std::nullopt) && 476c6f4e017SAgata Olender (paramTransferProtocolType == std::nullopt)) 477c6f4e017SAgata Olender { 478c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must " 479c6f4e017SAgata Olender "contain specified protocol type or param " 480c6f4e017SAgata Olender "TransferProtocolType must be provided."; 481c6f4e017SAgata Olender 482c6f4e017SAgata Olender messages::resourceAtUriInUnknownFormat(res, imageUrl); 483c6f4e017SAgata Olender 484c6f4e017SAgata Olender return false; 485c6f4e017SAgata Olender } 486c6f4e017SAgata Olender 487c6f4e017SAgata Olender // valid transfer protocol provided both with URI and param 488c6f4e017SAgata Olender if ((paramTransferProtocolType != std::nullopt) && 489c6f4e017SAgata Olender (uriTransferProtocolType != std::nullopt)) 490c6f4e017SAgata Olender { 491c6f4e017SAgata Olender // check if protocol is the same for URI and param 492c6f4e017SAgata Olender if (*paramTransferProtocolType != *uriTransferProtocolType) 493c6f4e017SAgata Olender { 494c6f4e017SAgata Olender BMCWEB_LOG_ERROR << "Request action parameter " 495c6f4e017SAgata Olender "TransferProtocolType must contain the " 496c6f4e017SAgata Olender "same protocol type as protocol type " 497c6f4e017SAgata Olender "provided with param imageUrl."; 498c6f4e017SAgata Olender 499c6f4e017SAgata Olender messages::actionParameterValueTypeError( 500c6f4e017SAgata Olender res, *transferProtocolType, "TransferProtocolType", 501c6f4e017SAgata Olender "InsertMedia"); 502c6f4e017SAgata Olender 503c6f4e017SAgata Olender return false; 504c6f4e017SAgata Olender } 505c6f4e017SAgata Olender } 506c6f4e017SAgata Olender 507c6f4e017SAgata Olender // validation passed 508c6f4e017SAgata Olender // add protocol to URI if needed 509c6f4e017SAgata Olender if (uriTransferProtocolType == std::nullopt) 510c6f4e017SAgata Olender { 511c6f4e017SAgata Olender imageUrl = getUriWithTransferProtocol(imageUrl, 512c6f4e017SAgata Olender *paramTransferProtocolType); 513c6f4e017SAgata Olender } 514c6f4e017SAgata Olender 515c6f4e017SAgata Olender return true; 516c6f4e017SAgata Olender } 517c6f4e017SAgata Olender 518c6f4e017SAgata Olender /** 519e13c2760SPrzemyslaw Czarnowski * @brief Function handles POST method request. 520e13c2760SPrzemyslaw Czarnowski * 521e13c2760SPrzemyslaw Czarnowski * Analyzes POST body message before sends Reset request data to dbus. 522e13c2760SPrzemyslaw Czarnowski */ 523e13c2760SPrzemyslaw Czarnowski void doPost(crow::Response& res, const crow::Request& req, 524e13c2760SPrzemyslaw Czarnowski const std::vector<std::string>& params) override 525e13c2760SPrzemyslaw Czarnowski { 526e13c2760SPrzemyslaw Czarnowski auto aResp = std::make_shared<AsyncResp>(res); 527e13c2760SPrzemyslaw Czarnowski 528e13c2760SPrzemyslaw Czarnowski if (params.size() != 2) 529e13c2760SPrzemyslaw Czarnowski { 530e13c2760SPrzemyslaw Czarnowski messages::internalError(res); 531e13c2760SPrzemyslaw Czarnowski return; 532e13c2760SPrzemyslaw Czarnowski } 533e13c2760SPrzemyslaw Czarnowski 534e13c2760SPrzemyslaw Czarnowski // take resource name from URL 535e13c2760SPrzemyslaw Czarnowski const std::string& resName = params[1]; 536e13c2760SPrzemyslaw Czarnowski 537e13c2760SPrzemyslaw Czarnowski if (params[0] != "bmc") 538e13c2760SPrzemyslaw Czarnowski { 539e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound(res, "VirtualMedia.Insert", resName); 540e13c2760SPrzemyslaw Czarnowski 541e13c2760SPrzemyslaw Czarnowski return; 542e13c2760SPrzemyslaw Czarnowski } 543e13c2760SPrzemyslaw Czarnowski 544e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 545e13c2760SPrzemyslaw Czarnowski [this, aResp{std::move(aResp)}, req, 546e13c2760SPrzemyslaw Czarnowski resName](const boost::system::error_code ec, 547e13c2760SPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 548e13c2760SPrzemyslaw Czarnowski if (ec) 549e13c2760SPrzemyslaw Czarnowski { 550e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 551e13c2760SPrzemyslaw Czarnowski << ec; 552e13c2760SPrzemyslaw Czarnowski messages::internalError(aResp->res); 553e13c2760SPrzemyslaw Czarnowski 554e13c2760SPrzemyslaw Czarnowski return; 555e13c2760SPrzemyslaw Czarnowski } 556e13c2760SPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 557e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 558e13c2760SPrzemyslaw Czarnowski 559e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 560e13c2760SPrzemyslaw Czarnowski [this, service, resName, req, aResp{std::move(aResp)}]( 561e13c2760SPrzemyslaw Czarnowski const boost::system::error_code ec, 562e13c2760SPrzemyslaw Czarnowski ManagedObjectType& subtree) { 563e13c2760SPrzemyslaw Czarnowski if (ec) 564e13c2760SPrzemyslaw Czarnowski { 565e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 566e13c2760SPrzemyslaw Czarnowski 567e13c2760SPrzemyslaw Czarnowski return; 568e13c2760SPrzemyslaw Czarnowski } 569e13c2760SPrzemyslaw Czarnowski 570e13c2760SPrzemyslaw Czarnowski for (const auto& object : subtree) 571e13c2760SPrzemyslaw Czarnowski { 572e13c2760SPrzemyslaw Czarnowski const std::string& path = 573e13c2760SPrzemyslaw Czarnowski static_cast<const std::string&>(object.first); 574e13c2760SPrzemyslaw Czarnowski 575f23b7296SEd Tanous std::size_t lastIndex = path.rfind('/'); 576e13c2760SPrzemyslaw Czarnowski if (lastIndex == std::string::npos) 577e13c2760SPrzemyslaw Czarnowski { 578e13c2760SPrzemyslaw Czarnowski continue; 579e13c2760SPrzemyslaw Czarnowski } 580e13c2760SPrzemyslaw Czarnowski 581e13c2760SPrzemyslaw Czarnowski lastIndex += 1; 582e13c2760SPrzemyslaw Czarnowski 583e13c2760SPrzemyslaw Czarnowski if (path.substr(lastIndex) == resName) 584e13c2760SPrzemyslaw Czarnowski { 585e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Proxy"); 586e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 587e13c2760SPrzemyslaw Czarnowski { 588e13c2760SPrzemyslaw Czarnowski // Not possible in proxy mode 589e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "InsertMedia not " 590e13c2760SPrzemyslaw Czarnowski "allowed in proxy mode"; 591e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound( 592e13c2760SPrzemyslaw Czarnowski aResp->res, "VirtualMedia.InsertMedia", 593e13c2760SPrzemyslaw Czarnowski resName); 594e13c2760SPrzemyslaw Czarnowski 595e13c2760SPrzemyslaw Czarnowski return; 596e13c2760SPrzemyslaw Czarnowski } 597e13c2760SPrzemyslaw Czarnowski 598e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Legacy"); 599c6f4e017SAgata Olender if (lastIndex == std::string::npos) 600e13c2760SPrzemyslaw Czarnowski { 601c6f4e017SAgata Olender continue; 602c6f4e017SAgata Olender } 603c6f4e017SAgata Olender 604e13c2760SPrzemyslaw Czarnowski // Legacy mode 605e13c2760SPrzemyslaw Czarnowski std::string imageUrl; 606c6f4e017SAgata Olender std::optional<std::string> userName; 607c6f4e017SAgata Olender std::optional<std::string> password; 608c6f4e017SAgata Olender std::optional<std::string> transferMethod; 609c6f4e017SAgata Olender std::optional<std::string> transferProtocolType; 610c6f4e017SAgata Olender std::optional<bool> writeProtected = true; 611c6f4e017SAgata Olender std::optional<bool> inserted; 612e13c2760SPrzemyslaw Czarnowski 6134e0453b1SGunnar Mills // Read obligatory parameters (url of image) 614d6da5bebSAdrian Ambrożewicz if (!json_util::readJson( 615d6da5bebSAdrian Ambrożewicz req, aResp->res, "Image", imageUrl, 616988fb7b2SAdrian Ambrożewicz "WriteProtected", writeProtected, 617988fb7b2SAdrian Ambrożewicz "UserName", userName, "Password", 618c6f4e017SAgata Olender password, "Inserted", inserted, 619c6f4e017SAgata Olender "TransferMethod", transferMethod, 620c6f4e017SAgata Olender "TransferProtocolType", 621c6f4e017SAgata Olender transferProtocolType)) 622e13c2760SPrzemyslaw Czarnowski { 623c6f4e017SAgata Olender BMCWEB_LOG_DEBUG << "Image is not provided"; 624e13c2760SPrzemyslaw Czarnowski return; 625e13c2760SPrzemyslaw Czarnowski } 626e13c2760SPrzemyslaw Czarnowski 627c6f4e017SAgata Olender bool paramsValid = validateParams( 628c6f4e017SAgata Olender aResp->res, imageUrl, inserted, 629c6f4e017SAgata Olender transferMethod, transferProtocolType); 630c6f4e017SAgata Olender 631c6f4e017SAgata Olender if (paramsValid == false) 632e13c2760SPrzemyslaw Czarnowski { 633e13c2760SPrzemyslaw Czarnowski return; 634e13c2760SPrzemyslaw Czarnowski } 635e13c2760SPrzemyslaw Czarnowski 636c6f4e017SAgata Olender // manager is irrelevant for VirtualMedia dbus 637c6f4e017SAgata Olender // calls 638c6f4e017SAgata Olender doMountVmLegacy( 639c6f4e017SAgata Olender std::move(aResp), service, resName, 640c6f4e017SAgata Olender imageUrl, !(*writeProtected), 641c6f4e017SAgata Olender std::move(*userName), std::move(*password)); 642e13c2760SPrzemyslaw Czarnowski 643e13c2760SPrzemyslaw Czarnowski return; 644e13c2760SPrzemyslaw Czarnowski } 645e13c2760SPrzemyslaw Czarnowski } 646e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Parent item not found"; 647e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound(aResp->res, "VirtualMedia", 648e13c2760SPrzemyslaw Czarnowski resName); 649e13c2760SPrzemyslaw Czarnowski }, 650e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 651e13c2760SPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 652e13c2760SPrzemyslaw Czarnowski }, 653e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 654e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 655e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 656e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 657e13c2760SPrzemyslaw Czarnowski } 658e13c2760SPrzemyslaw Czarnowski 6591214b7e7SGunnar Mills template <typename T> 6601214b7e7SGunnar Mills static void secureCleanup(T& value) 661988fb7b2SAdrian Ambrożewicz { 662988fb7b2SAdrian Ambrożewicz auto raw = const_cast<typename T::value_type*>(value.data()); 663988fb7b2SAdrian Ambrożewicz explicit_bzero(raw, value.size() * sizeof(*raw)); 664988fb7b2SAdrian Ambrożewicz } 665988fb7b2SAdrian Ambrożewicz 666988fb7b2SAdrian Ambrożewicz class Credentials 667988fb7b2SAdrian Ambrożewicz { 668988fb7b2SAdrian Ambrożewicz public: 669988fb7b2SAdrian Ambrożewicz Credentials(std::string&& user, std::string&& password) : 670988fb7b2SAdrian Ambrożewicz userBuf(std::move(user)), passBuf(std::move(password)) 6711214b7e7SGunnar Mills {} 672988fb7b2SAdrian Ambrożewicz 673988fb7b2SAdrian Ambrożewicz ~Credentials() 674988fb7b2SAdrian Ambrożewicz { 675988fb7b2SAdrian Ambrożewicz secureCleanup(userBuf); 676988fb7b2SAdrian Ambrożewicz secureCleanup(passBuf); 677988fb7b2SAdrian Ambrożewicz } 678988fb7b2SAdrian Ambrożewicz 679988fb7b2SAdrian Ambrożewicz const std::string& user() 680988fb7b2SAdrian Ambrożewicz { 681988fb7b2SAdrian Ambrożewicz return userBuf; 682988fb7b2SAdrian Ambrożewicz } 683988fb7b2SAdrian Ambrożewicz 684988fb7b2SAdrian Ambrożewicz const std::string& password() 685988fb7b2SAdrian Ambrożewicz { 686988fb7b2SAdrian Ambrożewicz return passBuf; 687988fb7b2SAdrian Ambrożewicz } 688988fb7b2SAdrian Ambrożewicz 689988fb7b2SAdrian Ambrożewicz private: 690988fb7b2SAdrian Ambrożewicz Credentials() = delete; 691988fb7b2SAdrian Ambrożewicz Credentials(const Credentials&) = delete; 692988fb7b2SAdrian Ambrożewicz Credentials& operator=(const Credentials&) = delete; 693988fb7b2SAdrian Ambrożewicz 694988fb7b2SAdrian Ambrożewicz std::string userBuf; 695988fb7b2SAdrian Ambrożewicz std::string passBuf; 696988fb7b2SAdrian Ambrożewicz }; 697988fb7b2SAdrian Ambrożewicz 698988fb7b2SAdrian Ambrożewicz class CredentialsProvider 699988fb7b2SAdrian Ambrożewicz { 700988fb7b2SAdrian Ambrożewicz public: 7011214b7e7SGunnar Mills template <typename T> 7021214b7e7SGunnar Mills struct Deleter 703988fb7b2SAdrian Ambrożewicz { 704988fb7b2SAdrian Ambrożewicz void operator()(T* buff) const 705988fb7b2SAdrian Ambrożewicz { 706988fb7b2SAdrian Ambrożewicz if (buff) 707988fb7b2SAdrian Ambrożewicz { 708988fb7b2SAdrian Ambrożewicz secureCleanup(*buff); 709988fb7b2SAdrian Ambrożewicz delete buff; 710988fb7b2SAdrian Ambrożewicz } 711988fb7b2SAdrian Ambrożewicz } 712988fb7b2SAdrian Ambrożewicz }; 713988fb7b2SAdrian Ambrożewicz 714988fb7b2SAdrian Ambrożewicz using Buffer = std::vector<char>; 715988fb7b2SAdrian Ambrożewicz using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>; 716988fb7b2SAdrian Ambrożewicz // Using explicit definition instead of std::function to avoid implicit 717988fb7b2SAdrian Ambrożewicz // conversions eg. stack copy instead of reference 718988fb7b2SAdrian Ambrożewicz using FormatterFunc = void(const std::string& username, 719988fb7b2SAdrian Ambrożewicz const std::string& password, Buffer& dest); 720988fb7b2SAdrian Ambrożewicz 721988fb7b2SAdrian Ambrożewicz CredentialsProvider(std::string&& user, std::string&& password) : 722988fb7b2SAdrian Ambrożewicz credentials(std::move(user), std::move(password)) 7231214b7e7SGunnar Mills {} 724988fb7b2SAdrian Ambrożewicz 725988fb7b2SAdrian Ambrożewicz const std::string& user() 726988fb7b2SAdrian Ambrożewicz { 727988fb7b2SAdrian Ambrożewicz return credentials.user(); 728988fb7b2SAdrian Ambrożewicz } 729988fb7b2SAdrian Ambrożewicz 730988fb7b2SAdrian Ambrożewicz const std::string& password() 731988fb7b2SAdrian Ambrożewicz { 732988fb7b2SAdrian Ambrożewicz return credentials.password(); 733988fb7b2SAdrian Ambrożewicz } 734988fb7b2SAdrian Ambrożewicz 735988fb7b2SAdrian Ambrożewicz SecureBuffer pack(const FormatterFunc formatter) 736988fb7b2SAdrian Ambrożewicz { 737988fb7b2SAdrian Ambrożewicz SecureBuffer packed{new Buffer{}}; 738988fb7b2SAdrian Ambrożewicz if (formatter) 739988fb7b2SAdrian Ambrożewicz { 740988fb7b2SAdrian Ambrożewicz formatter(credentials.user(), credentials.password(), *packed); 741988fb7b2SAdrian Ambrożewicz } 742988fb7b2SAdrian Ambrożewicz 743988fb7b2SAdrian Ambrożewicz return packed; 744988fb7b2SAdrian Ambrożewicz } 745988fb7b2SAdrian Ambrożewicz 746988fb7b2SAdrian Ambrożewicz private: 747988fb7b2SAdrian Ambrożewicz Credentials credentials; 748988fb7b2SAdrian Ambrożewicz }; 749988fb7b2SAdrian Ambrożewicz 750988fb7b2SAdrian Ambrożewicz // Wrapper for boost::async_pipe ensuring proper pipe cleanup 7511214b7e7SGunnar Mills template <typename Buffer> 7521214b7e7SGunnar Mills class Pipe 753988fb7b2SAdrian Ambrożewicz { 754988fb7b2SAdrian Ambrożewicz public: 755988fb7b2SAdrian Ambrożewicz using unix_fd = sdbusplus::message::unix_fd; 756988fb7b2SAdrian Ambrożewicz 757988fb7b2SAdrian Ambrożewicz Pipe(boost::asio::io_context& io, Buffer&& buffer) : 758988fb7b2SAdrian Ambrożewicz impl(io), buffer{std::move(buffer)} 7591214b7e7SGunnar Mills {} 760988fb7b2SAdrian Ambrożewicz 761988fb7b2SAdrian Ambrożewicz ~Pipe() 762988fb7b2SAdrian Ambrożewicz { 763988fb7b2SAdrian Ambrożewicz // Named pipe needs to be explicitly removed 764988fb7b2SAdrian Ambrożewicz impl.close(); 765988fb7b2SAdrian Ambrożewicz } 766988fb7b2SAdrian Ambrożewicz 767988fb7b2SAdrian Ambrożewicz unix_fd fd() 768988fb7b2SAdrian Ambrożewicz { 769988fb7b2SAdrian Ambrożewicz return unix_fd{impl.native_source()}; 770988fb7b2SAdrian Ambrożewicz } 771988fb7b2SAdrian Ambrożewicz 772988fb7b2SAdrian Ambrożewicz template <typename WriteHandler> 773988fb7b2SAdrian Ambrożewicz void async_write(WriteHandler&& handler) 774988fb7b2SAdrian Ambrożewicz { 775988fb7b2SAdrian Ambrożewicz impl.async_write_some(data(), std::forward<WriteHandler>(handler)); 776988fb7b2SAdrian Ambrożewicz } 777988fb7b2SAdrian Ambrożewicz 778988fb7b2SAdrian Ambrożewicz private: 779988fb7b2SAdrian Ambrożewicz // Specialization for pointer types 780988fb7b2SAdrian Ambrożewicz template <typename B = Buffer> 781988fb7b2SAdrian Ambrożewicz typename std::enable_if<boost::has_dereference<B>::value, 782988fb7b2SAdrian Ambrożewicz boost::asio::const_buffer>::type 783988fb7b2SAdrian Ambrożewicz data() 784988fb7b2SAdrian Ambrożewicz { 785988fb7b2SAdrian Ambrożewicz return boost::asio::buffer(*buffer); 786988fb7b2SAdrian Ambrożewicz } 787988fb7b2SAdrian Ambrożewicz 788988fb7b2SAdrian Ambrożewicz template <typename B = Buffer> 789988fb7b2SAdrian Ambrożewicz typename std::enable_if<!boost::has_dereference<B>::value, 790988fb7b2SAdrian Ambrożewicz boost::asio::const_buffer>::type 791988fb7b2SAdrian Ambrożewicz data() 792988fb7b2SAdrian Ambrożewicz { 793988fb7b2SAdrian Ambrożewicz return boost::asio::buffer(buffer); 794988fb7b2SAdrian Ambrożewicz } 795988fb7b2SAdrian Ambrożewicz 796988fb7b2SAdrian Ambrożewicz const std::string name; 797988fb7b2SAdrian Ambrożewicz boost::process::async_pipe impl; 798988fb7b2SAdrian Ambrożewicz Buffer buffer; 799988fb7b2SAdrian Ambrożewicz }; 800988fb7b2SAdrian Ambrożewicz 801e13c2760SPrzemyslaw Czarnowski /** 802e13c2760SPrzemyslaw Czarnowski * @brief Function transceives data with dbus directly. 803e13c2760SPrzemyslaw Czarnowski * 804e13c2760SPrzemyslaw Czarnowski * All BMC state properties will be retrieved before sending reset request. 805e13c2760SPrzemyslaw Czarnowski */ 806d6da5bebSAdrian Ambrożewicz void doMountVmLegacy(std::shared_ptr<AsyncResp> asyncResp, 807e13c2760SPrzemyslaw Czarnowski const std::string& service, const std::string& name, 808988fb7b2SAdrian Ambrożewicz const std::string& imageUrl, const bool rw, 809988fb7b2SAdrian Ambrożewicz std::string&& userName, std::string&& password) 810e13c2760SPrzemyslaw Czarnowski { 811988fb7b2SAdrian Ambrożewicz using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>; 812988fb7b2SAdrian Ambrożewicz constexpr const size_t secretLimit = 1024; 813988fb7b2SAdrian Ambrożewicz 814988fb7b2SAdrian Ambrożewicz std::shared_ptr<SecurePipe> secretPipe; 815988fb7b2SAdrian Ambrożewicz std::variant<int, SecurePipe::unix_fd> unixFd = -1; 816988fb7b2SAdrian Ambrożewicz 817988fb7b2SAdrian Ambrożewicz if (!userName.empty() || !password.empty()) 818988fb7b2SAdrian Ambrożewicz { 819988fb7b2SAdrian Ambrożewicz // Encapsulate in safe buffer 820988fb7b2SAdrian Ambrożewicz CredentialsProvider credentials(std::move(userName), 821988fb7b2SAdrian Ambrożewicz std::move(password)); 822988fb7b2SAdrian Ambrożewicz 823988fb7b2SAdrian Ambrożewicz // Payload must contain data + NULL delimiters 824988fb7b2SAdrian Ambrożewicz if (credentials.user().size() + credentials.password().size() + 2 > 825988fb7b2SAdrian Ambrożewicz secretLimit) 826988fb7b2SAdrian Ambrożewicz { 827988fb7b2SAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Credentials too long to handle"; 828988fb7b2SAdrian Ambrożewicz messages::unrecognizedRequestBody(asyncResp->res); 829988fb7b2SAdrian Ambrożewicz return; 830988fb7b2SAdrian Ambrożewicz } 831988fb7b2SAdrian Ambrożewicz 832988fb7b2SAdrian Ambrożewicz // Pack secret 833988fb7b2SAdrian Ambrożewicz auto secret = credentials.pack([](const auto& user, 834988fb7b2SAdrian Ambrożewicz const auto& pass, auto& buff) { 835988fb7b2SAdrian Ambrożewicz std::copy(user.begin(), user.end(), std::back_inserter(buff)); 836988fb7b2SAdrian Ambrożewicz buff.push_back('\0'); 837988fb7b2SAdrian Ambrożewicz std::copy(pass.begin(), pass.end(), std::back_inserter(buff)); 838988fb7b2SAdrian Ambrożewicz buff.push_back('\0'); 839988fb7b2SAdrian Ambrożewicz }); 840988fb7b2SAdrian Ambrożewicz 841988fb7b2SAdrian Ambrożewicz // Open pipe 842988fb7b2SAdrian Ambrożewicz secretPipe = std::make_shared<SecurePipe>( 843988fb7b2SAdrian Ambrożewicz crow::connections::systemBus->get_io_context(), 844988fb7b2SAdrian Ambrożewicz std::move(secret)); 845988fb7b2SAdrian Ambrożewicz unixFd = secretPipe->fd(); 846988fb7b2SAdrian Ambrożewicz 847988fb7b2SAdrian Ambrożewicz // Pass secret over pipe 848988fb7b2SAdrian Ambrożewicz secretPipe->async_write( 849f5b16f03SVikram Bodireddy [asyncResp](const boost::system::error_code& ec, std::size_t) { 850988fb7b2SAdrian Ambrożewicz if (ec) 851988fb7b2SAdrian Ambrożewicz { 852988fb7b2SAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec; 853988fb7b2SAdrian Ambrożewicz messages::internalError(asyncResp->res); 854988fb7b2SAdrian Ambrożewicz } 855988fb7b2SAdrian Ambrożewicz }); 856988fb7b2SAdrian Ambrożewicz } 857988fb7b2SAdrian Ambrożewicz 858e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 859988fb7b2SAdrian Ambrożewicz [asyncResp, secretPipe](const boost::system::error_code ec, 860988fb7b2SAdrian Ambrożewicz bool success) { 861e13c2760SPrzemyslaw Czarnowski if (ec) 862e13c2760SPrzemyslaw Czarnowski { 863e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 864e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 865d6da5bebSAdrian Ambrożewicz } 866d6da5bebSAdrian Ambrożewicz else if (!success) 867d6da5bebSAdrian Ambrożewicz { 868d6da5bebSAdrian Ambrożewicz BMCWEB_LOG_ERROR << "Service responded with error"; 869d6da5bebSAdrian Ambrożewicz messages::generalError(asyncResp->res); 870e13c2760SPrzemyslaw Czarnowski } 871e13c2760SPrzemyslaw Czarnowski }, 872e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, 873988fb7b2SAdrian Ambrożewicz "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw, 874988fb7b2SAdrian Ambrożewicz unixFd); 875e13c2760SPrzemyslaw Czarnowski } 876e13c2760SPrzemyslaw Czarnowski }; 877e13c2760SPrzemyslaw Czarnowski 878e13c2760SPrzemyslaw Czarnowski /** 879e13c2760SPrzemyslaw Czarnowski @brief EjectMedia action class 880e13c2760SPrzemyslaw Czarnowski */ 881e13c2760SPrzemyslaw Czarnowski class VirtualMediaActionEjectMedia : public Node 882e13c2760SPrzemyslaw Czarnowski { 883e13c2760SPrzemyslaw Czarnowski public: 88452cc112dSEd Tanous VirtualMediaActionEjectMedia(App& app) : 885e13c2760SPrzemyslaw Czarnowski Node(app, 886e13c2760SPrzemyslaw Czarnowski "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/" 887e13c2760SPrzemyslaw Czarnowski "VirtualMedia.EjectMedia", 888e13c2760SPrzemyslaw Czarnowski std::string(), std::string()) 889e13c2760SPrzemyslaw Czarnowski { 890e13c2760SPrzemyslaw Czarnowski entityPrivileges = { 891e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 892e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 893e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 894e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 895e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 896e13c2760SPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 897e13c2760SPrzemyslaw Czarnowski } 898e13c2760SPrzemyslaw Czarnowski 899e13c2760SPrzemyslaw Czarnowski private: 900e13c2760SPrzemyslaw Czarnowski /** 901e13c2760SPrzemyslaw Czarnowski * @brief Function handles POST method request. 902e13c2760SPrzemyslaw Czarnowski * 903e13c2760SPrzemyslaw Czarnowski * Analyzes POST body message before sends Reset request data to dbus. 904e13c2760SPrzemyslaw Czarnowski */ 905e13c2760SPrzemyslaw Czarnowski void doPost(crow::Response& res, const crow::Request& req, 906e13c2760SPrzemyslaw Czarnowski const std::vector<std::string>& params) override 907e13c2760SPrzemyslaw Czarnowski { 908e13c2760SPrzemyslaw Czarnowski auto aResp = std::make_shared<AsyncResp>(res); 909e13c2760SPrzemyslaw Czarnowski 910e13c2760SPrzemyslaw Czarnowski if (params.size() != 2) 911e13c2760SPrzemyslaw Czarnowski { 912e13c2760SPrzemyslaw Czarnowski messages::internalError(res); 913e13c2760SPrzemyslaw Czarnowski return; 914e13c2760SPrzemyslaw Czarnowski } 915e13c2760SPrzemyslaw Czarnowski 916e13c2760SPrzemyslaw Czarnowski // take resource name from URL 917e13c2760SPrzemyslaw Czarnowski const std::string& resName = params[1]; 918e13c2760SPrzemyslaw Czarnowski 919e13c2760SPrzemyslaw Czarnowski if (params[0] != "bmc") 920e13c2760SPrzemyslaw Czarnowski { 921e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound(res, "VirtualMedia.Eject", resName); 922e13c2760SPrzemyslaw Czarnowski 923e13c2760SPrzemyslaw Czarnowski return; 924e13c2760SPrzemyslaw Czarnowski } 925e13c2760SPrzemyslaw Czarnowski 926e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 927e13c2760SPrzemyslaw Czarnowski [this, aResp{std::move(aResp)}, req, 928e13c2760SPrzemyslaw Czarnowski resName](const boost::system::error_code ec, 929e13c2760SPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 930e13c2760SPrzemyslaw Czarnowski if (ec) 931e13c2760SPrzemyslaw Czarnowski { 932e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 933e13c2760SPrzemyslaw Czarnowski << ec; 934e13c2760SPrzemyslaw Czarnowski messages::internalError(aResp->res); 935e13c2760SPrzemyslaw Czarnowski 936e13c2760SPrzemyslaw Czarnowski return; 937e13c2760SPrzemyslaw Czarnowski } 938e13c2760SPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 939e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 940e13c2760SPrzemyslaw Czarnowski 941e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 942e13c2760SPrzemyslaw Czarnowski [this, resName, service, req, aResp{std::move(aResp)}]( 943e13c2760SPrzemyslaw Czarnowski const boost::system::error_code ec, 944e13c2760SPrzemyslaw Czarnowski ManagedObjectType& subtree) { 945e13c2760SPrzemyslaw Czarnowski if (ec) 946e13c2760SPrzemyslaw Czarnowski { 947e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "DBUS response error"; 948e13c2760SPrzemyslaw Czarnowski 949e13c2760SPrzemyslaw Czarnowski return; 950e13c2760SPrzemyslaw Czarnowski } 951e13c2760SPrzemyslaw Czarnowski 952e13c2760SPrzemyslaw Czarnowski for (const auto& object : subtree) 953e13c2760SPrzemyslaw Czarnowski { 954e13c2760SPrzemyslaw Czarnowski const std::string& path = 955e13c2760SPrzemyslaw Czarnowski static_cast<const std::string&>(object.first); 956e13c2760SPrzemyslaw Czarnowski 957f23b7296SEd Tanous std::size_t lastIndex = path.rfind('/'); 958e13c2760SPrzemyslaw Czarnowski if (lastIndex == std::string::npos) 959e13c2760SPrzemyslaw Czarnowski { 960e13c2760SPrzemyslaw Czarnowski continue; 961e13c2760SPrzemyslaw Czarnowski } 962e13c2760SPrzemyslaw Czarnowski 963e13c2760SPrzemyslaw Czarnowski lastIndex += 1; 964e13c2760SPrzemyslaw Czarnowski 965e13c2760SPrzemyslaw Czarnowski if (path.substr(lastIndex) == resName) 966e13c2760SPrzemyslaw Czarnowski { 967e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Proxy"); 968e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 969e13c2760SPrzemyslaw Czarnowski { 970e13c2760SPrzemyslaw Czarnowski // Proxy mode 971e13c2760SPrzemyslaw Czarnowski doVmAction(std::move(aResp), service, 972e13c2760SPrzemyslaw Czarnowski resName, false); 973e13c2760SPrzemyslaw Czarnowski } 974e13c2760SPrzemyslaw Czarnowski 975e13c2760SPrzemyslaw Czarnowski lastIndex = path.rfind("Legacy"); 976e13c2760SPrzemyslaw Czarnowski if (lastIndex != std::string::npos) 977e13c2760SPrzemyslaw Czarnowski { 978e13c2760SPrzemyslaw Czarnowski // Legacy mode 979e13c2760SPrzemyslaw Czarnowski doVmAction(std::move(aResp), service, 980e13c2760SPrzemyslaw Czarnowski resName, true); 981e13c2760SPrzemyslaw Czarnowski } 982e13c2760SPrzemyslaw Czarnowski 983e13c2760SPrzemyslaw Czarnowski return; 984e13c2760SPrzemyslaw Czarnowski } 985e13c2760SPrzemyslaw Czarnowski } 986e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "Parent item not found"; 987e13c2760SPrzemyslaw Czarnowski messages::resourceNotFound(aResp->res, "VirtualMedia", 988e13c2760SPrzemyslaw Czarnowski resName); 989e13c2760SPrzemyslaw Czarnowski }, 990e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia", 991e13c2760SPrzemyslaw Czarnowski "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 992e13c2760SPrzemyslaw Czarnowski }, 993e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 994e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 995e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 996e13c2760SPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 997e13c2760SPrzemyslaw Czarnowski } 998e13c2760SPrzemyslaw Czarnowski 999e13c2760SPrzemyslaw Czarnowski /** 1000e13c2760SPrzemyslaw Czarnowski * @brief Function transceives data with dbus directly. 1001e13c2760SPrzemyslaw Czarnowski * 1002e13c2760SPrzemyslaw Czarnowski * All BMC state properties will be retrieved before sending reset request. 1003e13c2760SPrzemyslaw Czarnowski */ 1004e13c2760SPrzemyslaw Czarnowski void doVmAction(std::shared_ptr<AsyncResp> asyncResp, 1005e13c2760SPrzemyslaw Czarnowski const std::string& service, const std::string& name, 1006e13c2760SPrzemyslaw Czarnowski bool legacy) 1007e13c2760SPrzemyslaw Czarnowski { 1008e13c2760SPrzemyslaw Czarnowski 1009e13c2760SPrzemyslaw Czarnowski // Legacy mount requires parameter with image 1010e13c2760SPrzemyslaw Czarnowski if (legacy) 1011e13c2760SPrzemyslaw Czarnowski { 1012e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1013e13c2760SPrzemyslaw Czarnowski [asyncResp](const boost::system::error_code ec) { 1014e13c2760SPrzemyslaw Czarnowski if (ec) 1015e13c2760SPrzemyslaw Czarnowski { 1016e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 1017e13c2760SPrzemyslaw Czarnowski 1018e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1019e13c2760SPrzemyslaw Czarnowski return; 1020e13c2760SPrzemyslaw Czarnowski } 1021e13c2760SPrzemyslaw Czarnowski }, 1022e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, 1023e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount"); 1024e13c2760SPrzemyslaw Czarnowski } 1025e13c2760SPrzemyslaw Czarnowski else // proxy 1026e13c2760SPrzemyslaw Czarnowski { 1027e13c2760SPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1028e13c2760SPrzemyslaw Czarnowski [asyncResp](const boost::system::error_code ec) { 1029e13c2760SPrzemyslaw Czarnowski if (ec) 1030e13c2760SPrzemyslaw Czarnowski { 1031e13c2760SPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; 1032e13c2760SPrzemyslaw Czarnowski 1033e13c2760SPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1034e13c2760SPrzemyslaw Czarnowski return; 1035e13c2760SPrzemyslaw Czarnowski } 1036e13c2760SPrzemyslaw Czarnowski }, 1037e13c2760SPrzemyslaw Czarnowski service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name, 1038e13c2760SPrzemyslaw Czarnowski "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount"); 1039e13c2760SPrzemyslaw Czarnowski } 1040e13c2760SPrzemyslaw Czarnowski } 1041e13c2760SPrzemyslaw Czarnowski }; 1042e13c2760SPrzemyslaw Czarnowski 1043107077deSPrzemyslaw Czarnowski class VirtualMediaCollection : public Node 1044107077deSPrzemyslaw Czarnowski { 1045107077deSPrzemyslaw Czarnowski public: 1046107077deSPrzemyslaw Czarnowski /* 1047107077deSPrzemyslaw Czarnowski * Default Constructor 1048107077deSPrzemyslaw Czarnowski */ 104952cc112dSEd Tanous VirtualMediaCollection(App& app) : 1050107077deSPrzemyslaw Czarnowski Node(app, "/redfish/v1/Managers/<str>/VirtualMedia/", std::string()) 1051107077deSPrzemyslaw Czarnowski { 1052107077deSPrzemyslaw Czarnowski entityPrivileges = { 1053107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 1054107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 1055107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 1056107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 1057107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 1058107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 1059107077deSPrzemyslaw Czarnowski } 1060107077deSPrzemyslaw Czarnowski 1061107077deSPrzemyslaw Czarnowski private: 1062107077deSPrzemyslaw Czarnowski /** 1063107077deSPrzemyslaw Czarnowski * Functions triggers appropriate requests on DBus 1064107077deSPrzemyslaw Czarnowski */ 1065f5b16f03SVikram Bodireddy void doGet(crow::Response& res, const crow::Request&, 1066107077deSPrzemyslaw Czarnowski const std::vector<std::string>& params) override 1067107077deSPrzemyslaw Czarnowski { 1068107077deSPrzemyslaw Czarnowski auto asyncResp = std::make_shared<AsyncResp>(res); 1069107077deSPrzemyslaw Czarnowski 1070107077deSPrzemyslaw Czarnowski // Check if there is required param, truly entering this shall be 1071107077deSPrzemyslaw Czarnowski // impossible 1072107077deSPrzemyslaw Czarnowski if (params.size() != 1) 1073107077deSPrzemyslaw Czarnowski { 1074107077deSPrzemyslaw Czarnowski messages::internalError(res); 1075107077deSPrzemyslaw Czarnowski 1076107077deSPrzemyslaw Czarnowski return; 1077107077deSPrzemyslaw Czarnowski } 1078107077deSPrzemyslaw Czarnowski 1079107077deSPrzemyslaw Czarnowski const std::string& name = params[0]; 1080107077deSPrzemyslaw Czarnowski 1081107077deSPrzemyslaw Czarnowski if (name != "bmc") 1082107077deSPrzemyslaw Czarnowski { 1083107077deSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, "VirtualMedia", name); 1084107077deSPrzemyslaw Czarnowski 1085107077deSPrzemyslaw Czarnowski return; 1086107077deSPrzemyslaw Czarnowski } 1087107077deSPrzemyslaw Czarnowski 1088107077deSPrzemyslaw Czarnowski res.jsonValue["@odata.type"] = 1089107077deSPrzemyslaw Czarnowski "#VirtualMediaCollection.VirtualMediaCollection"; 1090107077deSPrzemyslaw Czarnowski res.jsonValue["Name"] = "Virtual Media Services"; 1091107077deSPrzemyslaw Czarnowski res.jsonValue["@odata.id"] = 1092d6c414f3SPrzemyslaw Czarnowski "/redfish/v1/Managers/" + name + "/VirtualMedia"; 1093107077deSPrzemyslaw Czarnowski 1094107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1095107077deSPrzemyslaw Czarnowski [asyncResp, name](const boost::system::error_code ec, 1096107077deSPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 1097107077deSPrzemyslaw Czarnowski if (ec) 1098107077deSPrzemyslaw Czarnowski { 1099107077deSPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 1100107077deSPrzemyslaw Czarnowski << ec; 1101107077deSPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1102107077deSPrzemyslaw Czarnowski 1103107077deSPrzemyslaw Czarnowski return; 1104107077deSPrzemyslaw Czarnowski } 1105107077deSPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 1106107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 1107107077deSPrzemyslaw Czarnowski 1108107077deSPrzemyslaw Czarnowski getVmResourceList(asyncResp, service, name); 1109107077deSPrzemyslaw Czarnowski }, 1110107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 1111107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 1112107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 1113107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 1114107077deSPrzemyslaw Czarnowski } 1115107077deSPrzemyslaw Czarnowski }; 1116107077deSPrzemyslaw Czarnowski 1117107077deSPrzemyslaw Czarnowski class VirtualMedia : public Node 1118107077deSPrzemyslaw Czarnowski { 1119107077deSPrzemyslaw Czarnowski public: 1120107077deSPrzemyslaw Czarnowski /* 1121107077deSPrzemyslaw Czarnowski * Default Constructor 1122107077deSPrzemyslaw Czarnowski */ 112352cc112dSEd Tanous VirtualMedia(App& app) : 1124107077deSPrzemyslaw Czarnowski Node(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/", 1125107077deSPrzemyslaw Czarnowski std::string(), std::string()) 1126107077deSPrzemyslaw Czarnowski { 1127107077deSPrzemyslaw Czarnowski entityPrivileges = { 1128107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::get, {{"Login"}}}, 1129107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::head, {{"Login"}}}, 1130107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 1131107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 1132107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 1133107077deSPrzemyslaw Czarnowski {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 1134107077deSPrzemyslaw Czarnowski } 1135107077deSPrzemyslaw Czarnowski 1136107077deSPrzemyslaw Czarnowski private: 1137107077deSPrzemyslaw Czarnowski /** 1138107077deSPrzemyslaw Czarnowski * Functions triggers appropriate requests on DBus 1139107077deSPrzemyslaw Czarnowski */ 1140f5b16f03SVikram Bodireddy void doGet(crow::Response& res, const crow::Request&, 1141107077deSPrzemyslaw Czarnowski const std::vector<std::string>& params) override 1142107077deSPrzemyslaw Czarnowski { 1143107077deSPrzemyslaw Czarnowski // Check if there is required param, truly entering this shall be 1144107077deSPrzemyslaw Czarnowski // impossible 1145107077deSPrzemyslaw Czarnowski if (params.size() != 2) 1146107077deSPrzemyslaw Czarnowski { 1147107077deSPrzemyslaw Czarnowski messages::internalError(res); 1148107077deSPrzemyslaw Czarnowski 1149107077deSPrzemyslaw Czarnowski res.end(); 1150107077deSPrzemyslaw Czarnowski return; 1151107077deSPrzemyslaw Czarnowski } 1152107077deSPrzemyslaw Czarnowski const std::string& name = params[0]; 1153107077deSPrzemyslaw Czarnowski const std::string& resName = params[1]; 1154107077deSPrzemyslaw Czarnowski 1155107077deSPrzemyslaw Czarnowski auto asyncResp = std::make_shared<AsyncResp>(res); 1156107077deSPrzemyslaw Czarnowski 1157107077deSPrzemyslaw Czarnowski if (name != "bmc") 1158107077deSPrzemyslaw Czarnowski { 1159107077deSPrzemyslaw Czarnowski messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName); 1160107077deSPrzemyslaw Czarnowski 1161107077deSPrzemyslaw Czarnowski return; 1162107077deSPrzemyslaw Czarnowski } 1163107077deSPrzemyslaw Czarnowski 1164107077deSPrzemyslaw Czarnowski crow::connections::systemBus->async_method_call( 1165107077deSPrzemyslaw Czarnowski [asyncResp, name, resName](const boost::system::error_code ec, 1166107077deSPrzemyslaw Czarnowski const GetObjectType& getObjectType) { 1167107077deSPrzemyslaw Czarnowski if (ec) 1168107077deSPrzemyslaw Czarnowski { 1169107077deSPrzemyslaw Czarnowski BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " 1170107077deSPrzemyslaw Czarnowski << ec; 1171107077deSPrzemyslaw Czarnowski messages::internalError(asyncResp->res); 1172107077deSPrzemyslaw Czarnowski 1173107077deSPrzemyslaw Czarnowski return; 1174107077deSPrzemyslaw Czarnowski } 1175107077deSPrzemyslaw Czarnowski std::string service = getObjectType.begin()->first; 1176107077deSPrzemyslaw Czarnowski BMCWEB_LOG_DEBUG << "GetObjectType: " << service; 1177107077deSPrzemyslaw Czarnowski 1178107077deSPrzemyslaw Czarnowski getVmData(asyncResp, service, name, resName); 1179107077deSPrzemyslaw Czarnowski }, 1180107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", 1181107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/object_mapper", 1182107077deSPrzemyslaw Czarnowski "xyz.openbmc_project.ObjectMapper", "GetObject", 1183107077deSPrzemyslaw Czarnowski "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); 1184107077deSPrzemyslaw Czarnowski } 1185107077deSPrzemyslaw Czarnowski }; 1186107077deSPrzemyslaw Czarnowski 1187107077deSPrzemyslaw Czarnowski } // namespace redfish 1188