xref: /openbmc/bmcweb/redfish-core/lib/virtual_media.hpp (revision e3648032f357195d186b7f4f02519fae10a90e41)
1107077deSPrzemyslaw Czarnowski /*
26be832e2SEd Tanous Copyright (c) 2018 Intel Corporation
36be832e2SEd Tanous 
46be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License");
56be832e2SEd Tanous you may not use this file except in compliance with the License.
66be832e2SEd Tanous You may obtain a copy of the License at
76be832e2SEd Tanous 
86be832e2SEd Tanous       http://www.apache.org/licenses/LICENSE-2.0
96be832e2SEd Tanous 
106be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software
116be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS,
126be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136be832e2SEd Tanous See the License for the specific language governing permissions and
146be832e2SEd Tanous limitations under the License.
15107077deSPrzemyslaw Czarnowski */
16107077deSPrzemyslaw Czarnowski #pragma once
17107077deSPrzemyslaw Czarnowski 
183ccb3adbSEd Tanous #include "account_service.hpp"
193ccb3adbSEd Tanous #include "app.hpp"
2079fdf63eSPrzemyslaw Czarnowski #include "async_resp.hpp"
2111e8f60dSEd Tanous #include "credential_pipe.hpp"
222b73119cSGeorge Liu #include "dbus_utility.hpp"
23739b87efSEd Tanous #include "generated/enums/virtual_media.hpp"
243ccb3adbSEd Tanous #include "query.hpp"
253ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
263ccb3adbSEd Tanous #include "utils/json_utils.hpp"
273ccb3adbSEd Tanous 
28ef4c65b7SEd Tanous #include <boost/url/format.hpp>
299e319cf0SAnna Platash #include <boost/url/url_view.hpp>
304a7fbefdSEd Tanous #include <boost/url/url_view_base.hpp>
31107077deSPrzemyslaw Czarnowski 
322b73119cSGeorge Liu #include <array>
333544d2a7SEd Tanous #include <ranges>
342b73119cSGeorge Liu #include <string_view>
352b73119cSGeorge Liu 
36107077deSPrzemyslaw Czarnowski namespace redfish
37107077deSPrzemyslaw Czarnowski {
38365a73f4SEd Tanous 
39365a73f4SEd Tanous enum class VmMode
40365a73f4SEd Tanous {
41365a73f4SEd Tanous     Invalid,
42365a73f4SEd Tanous     Legacy,
43365a73f4SEd Tanous     Proxy
44365a73f4SEd Tanous };
45365a73f4SEd Tanous 
parseObjectPathAndGetMode(const sdbusplus::message::object_path & itemPath,const std::string & resName)46bd79bce8SPatrick Williams inline VmMode parseObjectPathAndGetMode(
47bd79bce8SPatrick Williams     const sdbusplus::message::object_path& itemPath, const std::string& resName)
48365a73f4SEd Tanous {
49365a73f4SEd Tanous     std::string thisPath = itemPath.filename();
5062598e31SEd Tanous     BMCWEB_LOG_DEBUG("Filename: {}, ThisPath: {}", itemPath.str, thisPath);
51365a73f4SEd Tanous 
52365a73f4SEd Tanous     if (thisPath.empty())
53365a73f4SEd Tanous     {
54365a73f4SEd Tanous         return VmMode::Invalid;
55365a73f4SEd Tanous     }
56365a73f4SEd Tanous 
57365a73f4SEd Tanous     if (thisPath != resName)
58365a73f4SEd Tanous     {
59365a73f4SEd Tanous         return VmMode::Invalid;
60365a73f4SEd Tanous     }
61365a73f4SEd Tanous 
62365a73f4SEd Tanous     auto mode = itemPath.parent_path();
63365a73f4SEd Tanous     auto type = mode.parent_path();
64365a73f4SEd Tanous 
65365a73f4SEd Tanous     if (mode.filename().empty() || type.filename().empty())
66365a73f4SEd Tanous     {
67365a73f4SEd Tanous         return VmMode::Invalid;
68365a73f4SEd Tanous     }
69365a73f4SEd Tanous 
70365a73f4SEd Tanous     if (type.filename() != "VirtualMedia")
71365a73f4SEd Tanous     {
72365a73f4SEd Tanous         return VmMode::Invalid;
73365a73f4SEd Tanous     }
74365a73f4SEd Tanous     std::string modeStr = mode.filename();
75365a73f4SEd Tanous     if (modeStr == "Legacy")
76365a73f4SEd Tanous     {
77365a73f4SEd Tanous         return VmMode::Legacy;
78365a73f4SEd Tanous     }
79365a73f4SEd Tanous     if (modeStr == "Proxy")
80365a73f4SEd Tanous     {
81365a73f4SEd Tanous         return VmMode::Proxy;
82365a73f4SEd Tanous     }
83365a73f4SEd Tanous     return VmMode::Invalid;
84365a73f4SEd Tanous }
85365a73f4SEd Tanous 
8679fdf63eSPrzemyslaw Czarnowski using CheckItemHandler =
8779fdf63eSPrzemyslaw Czarnowski     std::function<void(const std::string& service, const std::string& resName,
8879fdf63eSPrzemyslaw Czarnowski                        const std::shared_ptr<bmcweb::AsyncResp>&,
8970cbdf53SGeorge Liu                        const std::pair<sdbusplus::message::object_path,
9080f79a40SMichael Shen                                        dbus::utility::DBusInterfacesMap>&)>;
9179fdf63eSPrzemyslaw Czarnowski 
92ac106bf6SEd Tanous inline void
findAndParseObject(const std::string & service,const std::string & resName,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,CheckItemHandler && handler)93ac106bf6SEd Tanous     findAndParseObject(const std::string& service, const std::string& resName,
94ac106bf6SEd Tanous                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9579fdf63eSPrzemyslaw Czarnowski                        CheckItemHandler&& handler)
9679fdf63eSPrzemyslaw Czarnowski {
975eb468daSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/VirtualMedia");
985eb468daSGeorge Liu     dbus::utility::getManagedObjects(
995eb468daSGeorge Liu         service, path,
1008cb2c024SEd Tanous         [service, resName, asyncResp, handler = std::move(handler)](
1018cb2c024SEd Tanous             const boost::system::error_code& ec,
10270cbdf53SGeorge Liu             const dbus::utility::ManagedObjectType& subtree) {
10379fdf63eSPrzemyslaw Czarnowski             if (ec)
10479fdf63eSPrzemyslaw Czarnowski             {
10562598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error");
10679fdf63eSPrzemyslaw Czarnowski 
10779fdf63eSPrzemyslaw Czarnowski                 return;
10879fdf63eSPrzemyslaw Czarnowski             }
10979fdf63eSPrzemyslaw Czarnowski 
11070cbdf53SGeorge Liu             for (const auto& item : subtree)
11179fdf63eSPrzemyslaw Czarnowski             {
11279fdf63eSPrzemyslaw Czarnowski                 VmMode mode = parseObjectPathAndGetMode(item.first, resName);
11379fdf63eSPrzemyslaw Czarnowski                 if (mode != VmMode::Invalid)
11479fdf63eSPrzemyslaw Czarnowski                 {
115ac106bf6SEd Tanous                     handler(service, resName, asyncResp, item);
11679fdf63eSPrzemyslaw Czarnowski                     return;
11779fdf63eSPrzemyslaw Czarnowski                 }
11879fdf63eSPrzemyslaw Czarnowski             }
11979fdf63eSPrzemyslaw Czarnowski 
12062598e31SEd Tanous             BMCWEB_LOG_DEBUG("Parent item not found");
121ac106bf6SEd Tanous             asyncResp->res.result(boost::beast::http::status::not_found);
1225eb468daSGeorge Liu         });
12379fdf63eSPrzemyslaw Czarnowski }
12479fdf63eSPrzemyslaw Czarnowski 
1259e319cf0SAnna Platash /**
1269e319cf0SAnna Platash  * @brief Function extracts transfer protocol name from URI.
1279e319cf0SAnna Platash  */
getTransferProtocolTypeFromUri(const std::string & imageUri)12867df073bSEd Tanous inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
12967df073bSEd Tanous {
1306fd29553SEd Tanous     boost::system::result<boost::urls::url_view> url =
131079360aeSEd Tanous         boost::urls::parse_uri(imageUri);
13267df073bSEd Tanous     if (!url)
13367df073bSEd Tanous     {
13467df073bSEd Tanous         return "None";
13567df073bSEd Tanous     }
136079360aeSEd Tanous     std::string_view scheme = url->scheme();
13767df073bSEd Tanous     if (scheme == "smb")
13867df073bSEd Tanous     {
13967df073bSEd Tanous         return "CIFS";
14067df073bSEd Tanous     }
14167df073bSEd Tanous     if (scheme == "https")
14267df073bSEd Tanous     {
14367df073bSEd Tanous         return "HTTPS";
14467df073bSEd Tanous     }
14567df073bSEd Tanous 
14667df073bSEd Tanous     return "None";
14767df073bSEd Tanous }
148107077deSPrzemyslaw Czarnowski 
149107077deSPrzemyslaw Czarnowski /**
150107077deSPrzemyslaw Czarnowski  * @brief Read all known properties from VM object interfaces
151107077deSPrzemyslaw Czarnowski  */
15222db1728SEd Tanous inline void
vmParseInterfaceObject(const dbus::utility::DBusInterfacesMap & interfaces,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)15380f79a40SMichael Shen     vmParseInterfaceObject(const dbus::utility::DBusInterfacesMap& interfaces,
154ac106bf6SEd Tanous                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
155107077deSPrzemyslaw Czarnowski {
1568a592810SEd Tanous     for (const auto& [interface, values] : interfaces)
157107077deSPrzemyslaw Czarnowski     {
158711ac7a9SEd Tanous         if (interface == "xyz.openbmc_project.VirtualMedia.MountPoint")
159107077deSPrzemyslaw Czarnowski         {
160711ac7a9SEd Tanous             for (const auto& [property, value] : values)
161107077deSPrzemyslaw Czarnowski             {
162711ac7a9SEd Tanous                 if (property == "EndpointId")
163107077deSPrzemyslaw Czarnowski                 {
164107077deSPrzemyslaw Czarnowski                     const std::string* endpointIdValue =
165711ac7a9SEd Tanous                         std::get_if<std::string>(&value);
166711ac7a9SEd Tanous                     if (endpointIdValue == nullptr)
167107077deSPrzemyslaw Czarnowski                     {
168711ac7a9SEd Tanous                         continue;
169711ac7a9SEd Tanous                     }
170107077deSPrzemyslaw Czarnowski                     if (!endpointIdValue->empty())
171107077deSPrzemyslaw Czarnowski                     {
172107077deSPrzemyslaw Czarnowski                         // Proxy mode
173ac106bf6SEd Tanous                         asyncResp->res
174711ac7a9SEd Tanous                             .jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
175d04ba325SPrzemyslaw Czarnowski                             *endpointIdValue;
176ac106bf6SEd Tanous                         asyncResp->res.jsonValue["TransferProtocolType"] =
177ac106bf6SEd Tanous                             "OEM";
178107077deSPrzemyslaw Czarnowski                     }
179107077deSPrzemyslaw Czarnowski                 }
180711ac7a9SEd Tanous                 if (property == "ImageURL")
181107077deSPrzemyslaw Czarnowski                 {
182107077deSPrzemyslaw Czarnowski                     const std::string* imageUrlValue =
183711ac7a9SEd Tanous                         std::get_if<std::string>(&value);
18426f6976fSEd Tanous                     if (imageUrlValue != nullptr && !imageUrlValue->empty())
185107077deSPrzemyslaw Czarnowski                     {
186da4784d8SPrzemyslaw Czarnowski                         std::filesystem::path filePath = *imageUrlValue;
187da4784d8SPrzemyslaw Czarnowski                         if (!filePath.has_filename())
188da4784d8SPrzemyslaw Czarnowski                         {
1899e319cf0SAnna Platash                             // this will handle https share, which not
1909e319cf0SAnna Platash                             // necessarily has to have filename given.
191ac106bf6SEd Tanous                             asyncResp->res.jsonValue["ImageName"] = "";
192da4784d8SPrzemyslaw Czarnowski                         }
193da4784d8SPrzemyslaw Czarnowski                         else
194da4784d8SPrzemyslaw Czarnowski                         {
195ac106bf6SEd Tanous                             asyncResp->res.jsonValue["ImageName"] =
1969e319cf0SAnna Platash                                 filePath.filename();
197da4784d8SPrzemyslaw Czarnowski                         }
198da4784d8SPrzemyslaw Czarnowski 
199ac106bf6SEd Tanous                         asyncResp->res.jsonValue["Image"] = *imageUrlValue;
200ac106bf6SEd Tanous                         asyncResp->res.jsonValue["TransferProtocolType"] =
2019e319cf0SAnna Platash                             getTransferProtocolTypeFromUri(*imageUrlValue);
2029e319cf0SAnna Platash 
203ac106bf6SEd Tanous                         asyncResp->res.jsonValue["ConnectedVia"] =
204739b87efSEd Tanous                             virtual_media::ConnectedVia::URI;
205107077deSPrzemyslaw Czarnowski                     }
206107077deSPrzemyslaw Czarnowski                 }
207711ac7a9SEd Tanous                 if (property == "WriteProtected")
2089e319cf0SAnna Platash                 {
209711ac7a9SEd Tanous                     const bool* writeProtectedValue = std::get_if<bool>(&value);
210e662eae8SEd Tanous                     if (writeProtectedValue != nullptr)
2119e319cf0SAnna Platash                     {
212ac106bf6SEd Tanous                         asyncResp->res.jsonValue["WriteProtected"] =
2139e319cf0SAnna Platash                             *writeProtectedValue;
2149e319cf0SAnna Platash                     }
2159e319cf0SAnna Platash                 }
2169e319cf0SAnna Platash             }
217107077deSPrzemyslaw Czarnowski         }
218711ac7a9SEd Tanous         if (interface == "xyz.openbmc_project.VirtualMedia.Process")
219711ac7a9SEd Tanous         {
220711ac7a9SEd Tanous             for (const auto& [property, value] : values)
221711ac7a9SEd Tanous             {
222711ac7a9SEd Tanous                 if (property == "Active")
223711ac7a9SEd Tanous                 {
224711ac7a9SEd Tanous                     const bool* activeValue = std::get_if<bool>(&value);
225e662eae8SEd Tanous                     if (activeValue == nullptr)
226711ac7a9SEd Tanous                     {
22762598e31SEd Tanous                         BMCWEB_LOG_DEBUG("Value Active not found");
228711ac7a9SEd Tanous                         return;
229711ac7a9SEd Tanous                     }
230ac106bf6SEd Tanous                     asyncResp->res.jsonValue["Inserted"] = *activeValue;
231711ac7a9SEd Tanous 
232e05aec50SEd Tanous                     if (*activeValue)
233711ac7a9SEd Tanous                     {
234ac106bf6SEd Tanous                         asyncResp->res.jsonValue["ConnectedVia"] =
235739b87efSEd Tanous                             virtual_media::ConnectedVia::Applet;
236711ac7a9SEd Tanous                     }
237711ac7a9SEd Tanous                 }
238711ac7a9SEd Tanous             }
239711ac7a9SEd Tanous         }
240107077deSPrzemyslaw Czarnowski     }
241107077deSPrzemyslaw Czarnowski }
242107077deSPrzemyslaw Czarnowski 
243107077deSPrzemyslaw Czarnowski /**
244107077deSPrzemyslaw Czarnowski  * @brief Fill template for Virtual Media Item.
245107077deSPrzemyslaw Czarnowski  */
vmItemTemplate(const std::string & name,const std::string & resName)24622db1728SEd Tanous inline nlohmann::json vmItemTemplate(const std::string& name,
247107077deSPrzemyslaw Czarnowski                                      const std::string& resName)
248107077deSPrzemyslaw Czarnowski {
249107077deSPrzemyslaw Czarnowski     nlohmann::json item;
250ef4c65b7SEd Tanous     item["@odata.id"] = boost::urls::format(
251ef4c65b7SEd Tanous         "/redfish/v1/Managers/{}/VirtualMedia/{}", name, resName);
25222db1728SEd Tanous 
253d04ba325SPrzemyslaw Czarnowski     item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
254107077deSPrzemyslaw Czarnowski     item["Name"] = "Virtual Removable Media";
255107077deSPrzemyslaw Czarnowski     item["Id"] = resName;
256107077deSPrzemyslaw Czarnowski     item["WriteProtected"] = true;
257739b87efSEd Tanous     item["ConnectedVia"] = virtual_media::ConnectedVia::NotConnected;
258613dabeaSEd Tanous     item["MediaTypes"] = nlohmann::json::array_t({"CD", "USBStick"});
259539d8c6bSEd Tanous     item["TransferMethod"] = virtual_media::TransferMethod::Stream;
260d04ba325SPrzemyslaw Czarnowski     item["Oem"]["OpenBMC"]["@odata.type"] =
261f958ed9cSEd Tanous         "#OpenBMCVirtualMedia.v1_0_0.VirtualMedia";
26215b89725SV-Sanjana     item["Oem"]["OpenBMC"]["@odata.id"] = boost::urls::format(
26315b89725SV-Sanjana         "/redfish/v1/Managers/{}/VirtualMedia/{}#/Oem/OpenBMC", name, resName);
264107077deSPrzemyslaw Czarnowski 
265107077deSPrzemyslaw Czarnowski     return item;
266107077deSPrzemyslaw Czarnowski }
267107077deSPrzemyslaw Czarnowski 
268107077deSPrzemyslaw Czarnowski /**
269107077deSPrzemyslaw Czarnowski  *  @brief Fills collection data
270107077deSPrzemyslaw Czarnowski  */
getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> asyncResp,const std::string & service,const std::string & name)271ac106bf6SEd Tanous inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
272107077deSPrzemyslaw Czarnowski                               const std::string& service,
273107077deSPrzemyslaw Czarnowski                               const std::string& name)
274107077deSPrzemyslaw Czarnowski {
27562598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get available Virtual Media resources.");
2765eb468daSGeorge Liu     sdbusplus::message::object_path objPath(
2775eb468daSGeorge Liu         "/xyz/openbmc_project/VirtualMedia");
2785eb468daSGeorge Liu     dbus::utility::getManagedObjects(
2795eb468daSGeorge Liu         service, objPath,
280ac106bf6SEd Tanous         [name, asyncResp{std::move(asyncResp)}](
2815e7e2dc5SEd Tanous             const boost::system::error_code& ec,
28202cad96eSEd Tanous             const dbus::utility::ManagedObjectType& subtree) {
283107077deSPrzemyslaw Czarnowski             if (ec)
284107077deSPrzemyslaw Czarnowski             {
28562598e31SEd Tanous                 BMCWEB_LOG_DEBUG("DBUS response error");
286107077deSPrzemyslaw Czarnowski                 return;
287107077deSPrzemyslaw Czarnowski             }
288ac106bf6SEd Tanous             nlohmann::json& members = asyncResp->res.jsonValue["Members"];
289107077deSPrzemyslaw Czarnowski             members = nlohmann::json::array();
290107077deSPrzemyslaw Czarnowski 
291107077deSPrzemyslaw Czarnowski             for (const auto& object : subtree)
292107077deSPrzemyslaw Czarnowski             {
293107077deSPrzemyslaw Czarnowski                 nlohmann::json item;
2942dfd18efSEd Tanous                 std::string path = object.first.filename();
2952dfd18efSEd Tanous                 if (path.empty())
296107077deSPrzemyslaw Czarnowski                 {
297107077deSPrzemyslaw Czarnowski                     continue;
298107077deSPrzemyslaw Czarnowski                 }
299107077deSPrzemyslaw Czarnowski 
300ef4c65b7SEd Tanous                 item["@odata.id"] = boost::urls::format(
301ef4c65b7SEd Tanous                     "/redfish/v1/Managers/{}/VirtualMedia/{}", name, path);
302107077deSPrzemyslaw Czarnowski                 members.emplace_back(std::move(item));
303107077deSPrzemyslaw Czarnowski             }
304ac106bf6SEd Tanous             asyncResp->res.jsonValue["Members@odata.count"] = members.size();
3055eb468daSGeorge Liu         });
306107077deSPrzemyslaw Czarnowski }
307107077deSPrzemyslaw Czarnowski 
30870cbdf53SGeorge Liu inline void
afterGetVmData(const std::string & name,const std::string &,const std::string & resName,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::pair<sdbusplus::message::object_path,dbus::utility::DBusInterfacesMap> & item)30970cbdf53SGeorge Liu     afterGetVmData(const std::string& name, const std::string& /*service*/,
31079fdf63eSPrzemyslaw Czarnowski                    const std::string& resName,
31179fdf63eSPrzemyslaw Czarnowski                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
31270cbdf53SGeorge Liu                    const std::pair<sdbusplus::message::object_path,
31380f79a40SMichael Shen                                    dbus::utility::DBusInterfacesMap>& item)
31479fdf63eSPrzemyslaw Czarnowski {
31579fdf63eSPrzemyslaw Czarnowski     VmMode mode = parseObjectPathAndGetMode(item.first, resName);
31679fdf63eSPrzemyslaw Czarnowski     if (mode == VmMode::Invalid)
31779fdf63eSPrzemyslaw Czarnowski     {
31879fdf63eSPrzemyslaw Czarnowski         return;
31979fdf63eSPrzemyslaw Czarnowski     }
32079fdf63eSPrzemyslaw Czarnowski 
32179fdf63eSPrzemyslaw Czarnowski     asyncResp->res.jsonValue = vmItemTemplate(name, resName);
32279fdf63eSPrzemyslaw Czarnowski 
32379fdf63eSPrzemyslaw Czarnowski     // Check if dbus path is Legacy type
32479fdf63eSPrzemyslaw Czarnowski     if (mode == VmMode::Legacy)
32579fdf63eSPrzemyslaw Czarnowski     {
326ef4c65b7SEd Tanous         asyncResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
327ef4c65b7SEd Tanous                                 ["target"] = boost::urls::format(
328ef4c65b7SEd Tanous             "/redfish/v1/Managers/{}/VirtualMedia/{}/Actions/VirtualMedia.InsertMedia",
329ef4c65b7SEd Tanous             name, resName);
33079fdf63eSPrzemyslaw Czarnowski     }
33179fdf63eSPrzemyslaw Czarnowski 
33279fdf63eSPrzemyslaw Czarnowski     vmParseInterfaceObject(item.second, asyncResp);
33379fdf63eSPrzemyslaw Czarnowski 
334ef4c65b7SEd Tanous     asyncResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"]
335ef4c65b7SEd Tanous                             ["target"] = boost::urls::format(
336ef4c65b7SEd Tanous         "/redfish/v1/Managers/{}/VirtualMedia/{}/Actions/VirtualMedia.EjectMedia",
337ef4c65b7SEd Tanous         name, resName);
33879fdf63eSPrzemyslaw Czarnowski }
33979fdf63eSPrzemyslaw Czarnowski 
340107077deSPrzemyslaw Czarnowski /**
341107077deSPrzemyslaw Czarnowski  *  @brief Fills data for specific resource
342107077deSPrzemyslaw Czarnowski  */
getVmData(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & service,const std::string & name,const std::string & resName)343ac106bf6SEd Tanous inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
344107077deSPrzemyslaw Czarnowski                       const std::string& service, const std::string& name,
345107077deSPrzemyslaw Czarnowski                       const std::string& resName)
346107077deSPrzemyslaw Czarnowski {
34762598e31SEd Tanous     BMCWEB_LOG_DEBUG("Get Virtual Media resource data.");
348107077deSPrzemyslaw Czarnowski 
349ac106bf6SEd Tanous     findAndParseObject(service, resName, asyncResp,
35070cbdf53SGeorge Liu                        std::bind_front(afterGetVmData, name));
351107077deSPrzemyslaw Czarnowski }
352107077deSPrzemyslaw Czarnowski 
353e13c2760SPrzemyslaw Czarnowski /**
354c6f4e017SAgata Olender  * @brief Transfer protocols supported for InsertMedia action.
355c6f4e017SAgata Olender  *
356c6f4e017SAgata Olender  */
357c6f4e017SAgata Olender enum class TransferProtocol
358c6f4e017SAgata Olender {
359c6f4e017SAgata Olender     https,
360c6f4e017SAgata Olender     smb,
361c6f4e017SAgata Olender     invalid
362c6f4e017SAgata Olender };
363c6f4e017SAgata Olender 
364c6f4e017SAgata Olender /**
365c6f4e017SAgata Olender  * @brief Function extracts transfer protocol type from URI.
366c6f4e017SAgata Olender  *
367c6f4e017SAgata Olender  */
36867df073bSEd Tanous inline std::optional<TransferProtocol>
getTransferProtocolFromUri(const boost::urls::url_view_base & imageUri)3694a7fbefdSEd Tanous     getTransferProtocolFromUri(const boost::urls::url_view_base& imageUri)
37067df073bSEd Tanous {
371079360aeSEd Tanous     std::string_view scheme = imageUri.scheme();
37267df073bSEd Tanous     if (scheme == "smb")
37367df073bSEd Tanous     {
37467df073bSEd Tanous         return TransferProtocol::smb;
37567df073bSEd Tanous     }
37667df073bSEd Tanous     if (scheme == "https")
37767df073bSEd Tanous     {
37867df073bSEd Tanous         return TransferProtocol::https;
37967df073bSEd Tanous     }
38067df073bSEd Tanous     if (!scheme.empty())
38167df073bSEd Tanous     {
38267df073bSEd Tanous         return TransferProtocol::invalid;
38367df073bSEd Tanous     }
38467df073bSEd Tanous 
38567df073bSEd Tanous     return {};
38667df073bSEd Tanous }
387c6f4e017SAgata Olender 
388c6f4e017SAgata Olender /**
389c6f4e017SAgata Olender  * @brief Function convert transfer protocol from string param.
390c6f4e017SAgata Olender  *
391c6f4e017SAgata Olender  */
getTransferProtocolFromParam(const std::optional<std::string> & transferProtocolType)39222db1728SEd Tanous inline std::optional<TransferProtocol> getTransferProtocolFromParam(
393c6f4e017SAgata Olender     const std::optional<std::string>& transferProtocolType)
394c6f4e017SAgata Olender {
395e01d0c36SEd Tanous     if (!transferProtocolType)
396c6f4e017SAgata Olender     {
397c6f4e017SAgata Olender         return {};
398c6f4e017SAgata Olender     }
399c6f4e017SAgata Olender 
400c6f4e017SAgata Olender     if (*transferProtocolType == "CIFS")
401c6f4e017SAgata Olender     {
402c6f4e017SAgata Olender         return TransferProtocol::smb;
403c6f4e017SAgata Olender     }
404c6f4e017SAgata Olender 
405c6f4e017SAgata Olender     if (*transferProtocolType == "HTTPS")
406c6f4e017SAgata Olender     {
407c6f4e017SAgata Olender         return TransferProtocol::https;
408c6f4e017SAgata Olender     }
409c6f4e017SAgata Olender 
410c6f4e017SAgata Olender     return TransferProtocol::invalid;
411c6f4e017SAgata Olender }
412c6f4e017SAgata Olender 
413c6f4e017SAgata Olender /**
414c6f4e017SAgata Olender  * @brief Function extends URI with transfer protocol type.
415c6f4e017SAgata Olender  *
416c6f4e017SAgata Olender  */
getUriWithTransferProtocol(const std::string & imageUri,const TransferProtocol & transferProtocol)417bd79bce8SPatrick Williams inline std::string getUriWithTransferProtocol(
418bd79bce8SPatrick Williams     const std::string& imageUri, const TransferProtocol& transferProtocol)
419c6f4e017SAgata Olender {
420c6f4e017SAgata Olender     if (transferProtocol == TransferProtocol::smb)
421c6f4e017SAgata Olender     {
422c6f4e017SAgata Olender         return "smb://" + imageUri;
423c6f4e017SAgata Olender     }
424c6f4e017SAgata Olender 
425c6f4e017SAgata Olender     if (transferProtocol == TransferProtocol::https)
426c6f4e017SAgata Olender     {
427c6f4e017SAgata Olender         return "https://" + imageUri;
428c6f4e017SAgata Olender     }
429c6f4e017SAgata Olender 
430c6f4e017SAgata Olender     return imageUri;
431c6f4e017SAgata Olender }
432c6f4e017SAgata Olender 
4331f2a40ceSPrzemyslaw Czarnowski struct InsertMediaActionParams
4341f2a40ceSPrzemyslaw Czarnowski {
435120fa86aSPrzemyslaw Czarnowski     std::optional<std::string> imageUrl;
4361f2a40ceSPrzemyslaw Czarnowski     std::optional<std::string> userName;
4371f2a40ceSPrzemyslaw Czarnowski     std::optional<std::string> password;
4381f2a40ceSPrzemyslaw Czarnowski     std::optional<std::string> transferMethod;
4391f2a40ceSPrzemyslaw Czarnowski     std::optional<std::string> transferProtocolType;
4401f2a40ceSPrzemyslaw Czarnowski     std::optional<bool> writeProtected = true;
4411f2a40ceSPrzemyslaw Czarnowski     std::optional<bool> inserted;
4421f2a40ceSPrzemyslaw Czarnowski };
4431f2a40ceSPrzemyslaw Czarnowski 
444e13c2760SPrzemyslaw Czarnowski /**
445e13c2760SPrzemyslaw Czarnowski  * @brief Function transceives data with dbus directly.
446e13c2760SPrzemyslaw Czarnowski  *
447e13c2760SPrzemyslaw Czarnowski  * All BMC state properties will be retrieved before sending reset request.
448e13c2760SPrzemyslaw Czarnowski  */
doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & service,const std::string & name,const std::string & imageUrl,bool rw,std::string && userName,std::string && password)44922db1728SEd Tanous inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
450e13c2760SPrzemyslaw Czarnowski                             const std::string& service, const std::string& name,
45111e8f60dSEd Tanous                             const std::string& imageUrl, bool rw,
452988fb7b2SAdrian Ambrożewicz                             std::string&& userName, std::string&& password)
453e13c2760SPrzemyslaw Czarnowski {
45411e8f60dSEd Tanous     int fd = -1;
45511e8f60dSEd Tanous     std::shared_ptr<CredentialsPipe> secretPipe;
456988fb7b2SAdrian Ambrożewicz     if (!userName.empty() || !password.empty())
457988fb7b2SAdrian Ambrożewicz     {
458988fb7b2SAdrian Ambrożewicz         // Payload must contain data + NULL delimiters
45911e8f60dSEd Tanous         constexpr const size_t secretLimit = 1024;
46011e8f60dSEd Tanous         if (userName.size() + password.size() + 2 > secretLimit)
461988fb7b2SAdrian Ambrożewicz         {
46262598e31SEd Tanous             BMCWEB_LOG_ERROR("Credentials too long to handle");
463988fb7b2SAdrian Ambrożewicz             messages::unrecognizedRequestBody(asyncResp->res);
464988fb7b2SAdrian Ambrożewicz             return;
465988fb7b2SAdrian Ambrożewicz         }
466988fb7b2SAdrian Ambrożewicz 
467988fb7b2SAdrian Ambrożewicz         // Open pipe
46811e8f60dSEd Tanous         secretPipe = std::make_shared<CredentialsPipe>(
46911e8f60dSEd Tanous             crow::connections::systemBus->get_io_context());
4703bfa3b29SEd Tanous         fd = secretPipe->releaseFd();
471988fb7b2SAdrian Ambrożewicz 
472988fb7b2SAdrian Ambrożewicz         // Pass secret over pipe
47381ce609eSEd Tanous         secretPipe->asyncWrite(
47411e8f60dSEd Tanous             std::move(userName), std::move(password),
475bd79bce8SPatrick Williams             [asyncResp,
476bd79bce8SPatrick Williams              secretPipe](const boost::system::error_code& ec, std::size_t) {
477988fb7b2SAdrian Ambrożewicz                 if (ec)
478988fb7b2SAdrian Ambrożewicz                 {
47962598e31SEd Tanous                     BMCWEB_LOG_ERROR("Failed to pass secret: {}", ec);
480988fb7b2SAdrian Ambrożewicz                     messages::internalError(asyncResp->res);
481988fb7b2SAdrian Ambrożewicz                 }
482988fb7b2SAdrian Ambrożewicz             });
483988fb7b2SAdrian Ambrożewicz     }
484988fb7b2SAdrian Ambrożewicz 
485*e3648032SEd Tanous     std::variant<sdbusplus::message::unix_fd> unixFd(
48611e8f60dSEd Tanous         std::in_place_type<sdbusplus::message::unix_fd>, fd);
48711e8f60dSEd Tanous 
48811e8f60dSEd Tanous     sdbusplus::message::object_path path(
48911e8f60dSEd Tanous         "/xyz/openbmc_project/VirtualMedia/Legacy");
49011e8f60dSEd Tanous     path /= name;
491e13c2760SPrzemyslaw Czarnowski     crow::connections::systemBus->async_method_call(
492bd79bce8SPatrick Williams         [asyncResp,
493bd79bce8SPatrick Williams          secretPipe](const boost::system::error_code& ec, bool success) {
494e13c2760SPrzemyslaw Czarnowski             if (ec)
495e13c2760SPrzemyslaw Czarnowski             {
49662598e31SEd Tanous                 BMCWEB_LOG_ERROR("Bad D-Bus request error: {}", ec);
497e13c2760SPrzemyslaw Czarnowski                 messages::internalError(asyncResp->res);
49811e8f60dSEd Tanous                 return;
499d6da5bebSAdrian Ambrożewicz             }
50011e8f60dSEd Tanous             if (!success)
501d6da5bebSAdrian Ambrożewicz             {
50262598e31SEd Tanous                 BMCWEB_LOG_ERROR("Service responded with error");
50311e8f60dSEd Tanous                 messages::internalError(asyncResp->res);
504e13c2760SPrzemyslaw Czarnowski             }
505e13c2760SPrzemyslaw Czarnowski         },
50611e8f60dSEd Tanous         service, path.str, "xyz.openbmc_project.VirtualMedia.Legacy", "Mount",
50711e8f60dSEd Tanous         imageUrl, rw, unixFd);
508e13c2760SPrzemyslaw Czarnowski }
509e13c2760SPrzemyslaw Czarnowski 
510e13c2760SPrzemyslaw Czarnowski /**
511120fa86aSPrzemyslaw Czarnowski  * @brief Function validate parameters of insert media request.
512120fa86aSPrzemyslaw Czarnowski  *
513120fa86aSPrzemyslaw Czarnowski  */
validateParams(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & service,const std::string & resName,InsertMediaActionParams & actionParams)514120fa86aSPrzemyslaw Czarnowski inline void validateParams(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
515120fa86aSPrzemyslaw Czarnowski                            const std::string& service,
516120fa86aSPrzemyslaw Czarnowski                            const std::string& resName,
517120fa86aSPrzemyslaw Czarnowski                            InsertMediaActionParams& actionParams)
518120fa86aSPrzemyslaw Czarnowski {
51962598e31SEd Tanous     BMCWEB_LOG_DEBUG("Validation started");
520120fa86aSPrzemyslaw Czarnowski     // required param imageUrl must not be empty
521120fa86aSPrzemyslaw Czarnowski     if (!actionParams.imageUrl)
522120fa86aSPrzemyslaw Czarnowski     {
52362598e31SEd Tanous         BMCWEB_LOG_ERROR("Request action parameter Image is empty.");
524120fa86aSPrzemyslaw Czarnowski 
525120fa86aSPrzemyslaw Czarnowski         messages::propertyValueFormatError(asyncResp->res, "<empty>", "Image");
526120fa86aSPrzemyslaw Czarnowski 
527120fa86aSPrzemyslaw Czarnowski         return;
528120fa86aSPrzemyslaw Czarnowski     }
529120fa86aSPrzemyslaw Czarnowski 
530120fa86aSPrzemyslaw Czarnowski     // optional param inserted must be true
531e01d0c36SEd Tanous     if (actionParams.inserted && !*actionParams.inserted)
532120fa86aSPrzemyslaw Czarnowski     {
53362598e31SEd Tanous         BMCWEB_LOG_ERROR(
53462598e31SEd Tanous             "Request action optional parameter Inserted must be true.");
535120fa86aSPrzemyslaw Czarnowski 
536120fa86aSPrzemyslaw Czarnowski         messages::actionParameterNotSupported(asyncResp->res, "Inserted",
537120fa86aSPrzemyslaw Czarnowski                                               "InsertMedia");
538120fa86aSPrzemyslaw Czarnowski 
539120fa86aSPrzemyslaw Czarnowski         return;
540120fa86aSPrzemyslaw Czarnowski     }
541120fa86aSPrzemyslaw Czarnowski 
542120fa86aSPrzemyslaw Czarnowski     // optional param transferMethod must be stream
543e01d0c36SEd Tanous     if (actionParams.transferMethod &&
544120fa86aSPrzemyslaw Czarnowski         (*actionParams.transferMethod != "Stream"))
545120fa86aSPrzemyslaw Czarnowski     {
54662598e31SEd Tanous         BMCWEB_LOG_ERROR("Request action optional parameter "
54762598e31SEd Tanous                          "TransferMethod must be Stream.");
548120fa86aSPrzemyslaw Czarnowski 
549120fa86aSPrzemyslaw Czarnowski         messages::actionParameterNotSupported(asyncResp->res, "TransferMethod",
550120fa86aSPrzemyslaw Czarnowski                                               "InsertMedia");
551120fa86aSPrzemyslaw Czarnowski 
552120fa86aSPrzemyslaw Czarnowski         return;
553120fa86aSPrzemyslaw Czarnowski     }
5546fd29553SEd Tanous     boost::system::result<boost::urls::url_view> url =
555120fa86aSPrzemyslaw Czarnowski         boost::urls::parse_uri(*actionParams.imageUrl);
556120fa86aSPrzemyslaw Czarnowski     if (!url)
557120fa86aSPrzemyslaw Czarnowski     {
558120fa86aSPrzemyslaw Czarnowski         messages::actionParameterValueFormatError(
559120fa86aSPrzemyslaw Czarnowski             asyncResp->res, *actionParams.imageUrl, "Image", "InsertMedia");
560120fa86aSPrzemyslaw Czarnowski         return;
561120fa86aSPrzemyslaw Czarnowski     }
562120fa86aSPrzemyslaw Czarnowski     std::optional<TransferProtocol> uriTransferProtocolType =
563120fa86aSPrzemyslaw Czarnowski         getTransferProtocolFromUri(*url);
564120fa86aSPrzemyslaw Czarnowski 
565120fa86aSPrzemyslaw Czarnowski     std::optional<TransferProtocol> paramTransferProtocolType =
566120fa86aSPrzemyslaw Czarnowski         getTransferProtocolFromParam(actionParams.transferProtocolType);
567120fa86aSPrzemyslaw Czarnowski 
568120fa86aSPrzemyslaw Czarnowski     // ImageUrl does not contain valid protocol type
569e01d0c36SEd Tanous     if (uriTransferProtocolType &&
570e01d0c36SEd Tanous         *uriTransferProtocolType == TransferProtocol::invalid)
571120fa86aSPrzemyslaw Czarnowski     {
57262598e31SEd Tanous         BMCWEB_LOG_ERROR("Request action parameter ImageUrl must "
573120fa86aSPrzemyslaw Czarnowski                          "contain specified protocol type from list: "
57462598e31SEd Tanous                          "(smb, https).");
575120fa86aSPrzemyslaw Czarnowski 
576120fa86aSPrzemyslaw Czarnowski         messages::resourceAtUriInUnknownFormat(asyncResp->res, *url);
577120fa86aSPrzemyslaw Czarnowski 
578120fa86aSPrzemyslaw Czarnowski         return;
579120fa86aSPrzemyslaw Czarnowski     }
580120fa86aSPrzemyslaw Czarnowski 
581120fa86aSPrzemyslaw Czarnowski     // transferProtocolType should contain value from list
582e01d0c36SEd Tanous     if (paramTransferProtocolType &&
583e01d0c36SEd Tanous         *paramTransferProtocolType == TransferProtocol::invalid)
584120fa86aSPrzemyslaw Czarnowski     {
58562598e31SEd Tanous         BMCWEB_LOG_ERROR("Request action parameter TransferProtocolType "
586120fa86aSPrzemyslaw Czarnowski                          "must be provided with value from list: "
58762598e31SEd Tanous                          "(CIFS, HTTPS).");
588120fa86aSPrzemyslaw Czarnowski 
589e01d0c36SEd Tanous         messages::propertyValueNotInList(
590e01d0c36SEd Tanous             asyncResp->res, actionParams.transferProtocolType.value_or(""),
591120fa86aSPrzemyslaw Czarnowski             "TransferProtocolType");
592120fa86aSPrzemyslaw Czarnowski         return;
593120fa86aSPrzemyslaw Czarnowski     }
594120fa86aSPrzemyslaw Czarnowski 
595120fa86aSPrzemyslaw Czarnowski     // valid transfer protocol not provided either with URI nor param
596e01d0c36SEd Tanous     if (!uriTransferProtocolType && !paramTransferProtocolType)
597120fa86aSPrzemyslaw Czarnowski     {
59862598e31SEd Tanous         BMCWEB_LOG_ERROR("Request action parameter ImageUrl must "
599120fa86aSPrzemyslaw Czarnowski                          "contain specified protocol type or param "
60062598e31SEd Tanous                          "TransferProtocolType must be provided.");
601120fa86aSPrzemyslaw Czarnowski 
602120fa86aSPrzemyslaw Czarnowski         messages::resourceAtUriInUnknownFormat(asyncResp->res, *url);
603120fa86aSPrzemyslaw Czarnowski 
604120fa86aSPrzemyslaw Czarnowski         return;
605120fa86aSPrzemyslaw Czarnowski     }
606120fa86aSPrzemyslaw Czarnowski 
607120fa86aSPrzemyslaw Czarnowski     // valid transfer protocol provided both with URI and param
608e01d0c36SEd Tanous     if (paramTransferProtocolType && uriTransferProtocolType)
609120fa86aSPrzemyslaw Czarnowski     {
610120fa86aSPrzemyslaw Czarnowski         // check if protocol is the same for URI and param
611120fa86aSPrzemyslaw Czarnowski         if (*paramTransferProtocolType != *uriTransferProtocolType)
612120fa86aSPrzemyslaw Czarnowski         {
61362598e31SEd Tanous             BMCWEB_LOG_ERROR("Request action parameter "
614120fa86aSPrzemyslaw Czarnowski                              "TransferProtocolType must  contain the "
615120fa86aSPrzemyslaw Czarnowski                              "same protocol type as protocol type "
61662598e31SEd Tanous                              "provided with param imageUrl.");
617120fa86aSPrzemyslaw Czarnowski 
618120fa86aSPrzemyslaw Czarnowski             messages::actionParameterValueTypeError(
619e01d0c36SEd Tanous                 asyncResp->res, actionParams.transferProtocolType.value_or(""),
620120fa86aSPrzemyslaw Czarnowski                 "TransferProtocolType", "InsertMedia");
621120fa86aSPrzemyslaw Czarnowski 
622120fa86aSPrzemyslaw Czarnowski             return;
623120fa86aSPrzemyslaw Czarnowski         }
624120fa86aSPrzemyslaw Czarnowski     }
625120fa86aSPrzemyslaw Czarnowski 
626120fa86aSPrzemyslaw Czarnowski     // validation passed, add protocol to URI if needed
6277ead48e6SBoleslaw Ogonczyk Makowski     if (!uriTransferProtocolType && paramTransferProtocolType)
628120fa86aSPrzemyslaw Czarnowski     {
629120fa86aSPrzemyslaw Czarnowski         actionParams.imageUrl = getUriWithTransferProtocol(
630120fa86aSPrzemyslaw Czarnowski             *actionParams.imageUrl, *paramTransferProtocolType);
631120fa86aSPrzemyslaw Czarnowski     }
632120fa86aSPrzemyslaw Czarnowski 
633452bd8d8SJayaprakash Mutyala     if (!actionParams.userName)
634452bd8d8SJayaprakash Mutyala     {
635452bd8d8SJayaprakash Mutyala         actionParams.userName = "";
636452bd8d8SJayaprakash Mutyala     }
637452bd8d8SJayaprakash Mutyala 
638452bd8d8SJayaprakash Mutyala     if (!actionParams.password)
639452bd8d8SJayaprakash Mutyala     {
640452bd8d8SJayaprakash Mutyala         actionParams.password = "";
641452bd8d8SJayaprakash Mutyala     }
642452bd8d8SJayaprakash Mutyala 
643120fa86aSPrzemyslaw Czarnowski     doMountVmLegacy(asyncResp, service, resName, *actionParams.imageUrl,
644e01d0c36SEd Tanous                     !(actionParams.writeProtected.value_or(false)),
645120fa86aSPrzemyslaw Czarnowski                     std::move(*actionParams.userName),
646120fa86aSPrzemyslaw Czarnowski                     std::move(*actionParams.password));
647120fa86aSPrzemyslaw Czarnowski }
648120fa86aSPrzemyslaw Czarnowski 
649120fa86aSPrzemyslaw Czarnowski /**
650e13c2760SPrzemyslaw Czarnowski  * @brief Function transceives data with dbus directly.
651e13c2760SPrzemyslaw Czarnowski  *
652e13c2760SPrzemyslaw Czarnowski  * All BMC state properties will be retrieved before sending reset request.
653e13c2760SPrzemyslaw Czarnowski  */
doEjectAction(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & service,const std::string & name,bool legacy)65424e740a7SEd Tanous inline void doEjectAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
655e13c2760SPrzemyslaw Czarnowski                           const std::string& service, const std::string& name,
656e13c2760SPrzemyslaw Czarnowski                           bool legacy)
657e13c2760SPrzemyslaw Czarnowski {
658e13c2760SPrzemyslaw Czarnowski     // Legacy mount requires parameter with image
659e13c2760SPrzemyslaw Czarnowski     if (legacy)
660e13c2760SPrzemyslaw Czarnowski     {
661e13c2760SPrzemyslaw Czarnowski         crow::connections::systemBus->async_method_call(
6625e7e2dc5SEd Tanous             [asyncResp](const boost::system::error_code& ec) {
663e13c2760SPrzemyslaw Czarnowski                 if (ec)
664e13c2760SPrzemyslaw Czarnowski                 {
66562598e31SEd Tanous                     BMCWEB_LOG_ERROR("Bad D-Bus request error: {}", ec);
666e13c2760SPrzemyslaw Czarnowski 
667e13c2760SPrzemyslaw Czarnowski                     messages::internalError(asyncResp->res);
668e13c2760SPrzemyslaw Czarnowski                     return;
669e13c2760SPrzemyslaw Czarnowski                 }
670e13c2760SPrzemyslaw Czarnowski             },
671e13c2760SPrzemyslaw Czarnowski             service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
672e13c2760SPrzemyslaw Czarnowski             "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
673e13c2760SPrzemyslaw Czarnowski     }
674e13c2760SPrzemyslaw Czarnowski     else // proxy
675e13c2760SPrzemyslaw Czarnowski     {
676e13c2760SPrzemyslaw Czarnowski         crow::connections::systemBus->async_method_call(
6775e7e2dc5SEd Tanous             [asyncResp](const boost::system::error_code& ec) {
678e13c2760SPrzemyslaw Czarnowski                 if (ec)
679e13c2760SPrzemyslaw Czarnowski                 {
68062598e31SEd Tanous                     BMCWEB_LOG_ERROR("Bad D-Bus request error: {}", ec);
681e13c2760SPrzemyslaw Czarnowski 
682e13c2760SPrzemyslaw Czarnowski                     messages::internalError(asyncResp->res);
683e13c2760SPrzemyslaw Czarnowski                     return;
684e13c2760SPrzemyslaw Czarnowski                 }
685e13c2760SPrzemyslaw Czarnowski             },
686e13c2760SPrzemyslaw Czarnowski             service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
687e13c2760SPrzemyslaw Czarnowski             "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
688e13c2760SPrzemyslaw Czarnowski     }
689e13c2760SPrzemyslaw Czarnowski }
690e13c2760SPrzemyslaw Czarnowski 
handleManagersVirtualMediaActionInsertPost(crow::App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & name,const std::string & resName)69196825bebSEd Tanous inline void handleManagersVirtualMediaActionInsertPost(
69296825bebSEd Tanous     crow::App& app, const crow::Request& req,
69322db1728SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
69496825bebSEd Tanous     const std::string& name, const std::string& resName)
69596825bebSEd Tanous {
6963ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
69745ca1b86SEd Tanous     {
69845ca1b86SEd Tanous         return;
69945ca1b86SEd Tanous     }
70079fdf63eSPrzemyslaw Czarnowski 
70179fdf63eSPrzemyslaw Czarnowski     constexpr std::string_view action = "VirtualMedia.InsertMedia";
70222db1728SEd Tanous     if (name != "bmc")
703107077deSPrzemyslaw Czarnowski     {
70479fdf63eSPrzemyslaw Czarnowski         messages::resourceNotFound(asyncResp->res, action, resName);
705107077deSPrzemyslaw Czarnowski 
706107077deSPrzemyslaw Czarnowski         return;
707107077deSPrzemyslaw Czarnowski     }
70879fdf63eSPrzemyslaw Czarnowski     InsertMediaActionParams actionParams;
70998be3e39SEd Tanous 
710120fa86aSPrzemyslaw Czarnowski     // Read obligatory parameters (url of image)
711afc474aeSMyung Bae     if (!json_util::readJsonAction( //
712afc474aeSMyung Bae             req, asyncResp->res, //
713afc474aeSMyung Bae             "Image", actionParams.imageUrl, //
714afc474aeSMyung Bae             "Inserted", actionParams.inserted, //
715afc474aeSMyung Bae             "Password", actionParams.password, //
716afc474aeSMyung Bae             "TransferMethod", actionParams.transferMethod, //
717afc474aeSMyung Bae             "TransferProtocolType", actionParams.transferProtocolType, //
718afc474aeSMyung Bae             "UserName", actionParams.userName, //
719afc474aeSMyung Bae             "WriteProtected", actionParams.writeProtected //
720afc474aeSMyung Bae             ))
72198be3e39SEd Tanous     {
72298be3e39SEd Tanous         return;
72398be3e39SEd Tanous     }
724107077deSPrzemyslaw Czarnowski 
7252b73119cSGeorge Liu     dbus::utility::getDbusObject(
7262b73119cSGeorge Liu         "/xyz/openbmc_project/VirtualMedia", {},
72779fdf63eSPrzemyslaw Czarnowski         [asyncResp, action, actionParams,
7282b73119cSGeorge Liu          resName](const boost::system::error_code& ec,
729002d39b4SEd Tanous                   const dbus::utility::MapperGetObject& getObjectType) mutable {
73022db1728SEd Tanous             if (ec)
73122db1728SEd Tanous             {
73262598e31SEd Tanous                 BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", ec);
73379fdf63eSPrzemyslaw Czarnowski                 messages::resourceNotFound(asyncResp->res, action, resName);
734107077deSPrzemyslaw Czarnowski 
73522db1728SEd Tanous                 return;
73622db1728SEd Tanous             }
73779fdf63eSPrzemyslaw Czarnowski 
73822db1728SEd Tanous             std::string service = getObjectType.begin()->first;
73962598e31SEd Tanous             BMCWEB_LOG_DEBUG("GetObjectType: {}", service);
74022db1728SEd Tanous 
7415eb468daSGeorge Liu             sdbusplus::message::object_path path(
7425eb468daSGeorge Liu                 "/xyz/openbmc_project/VirtualMedia");
7435eb468daSGeorge Liu             dbus::utility::getManagedObjects(
7445eb468daSGeorge Liu                 service, path,
7455eb468daSGeorge Liu                 [service, resName, action, actionParams, asyncResp](
7465eb468daSGeorge Liu                     const boost::system::error_code& ec2,
7475eb468daSGeorge Liu                     const dbus::utility::ManagedObjectType& subtree) mutable {
7488a592810SEd Tanous                     if (ec2)
74922db1728SEd Tanous                     {
75079fdf63eSPrzemyslaw Czarnowski                         // Not possible in proxy mode
75162598e31SEd Tanous                         BMCWEB_LOG_DEBUG("InsertMedia not "
75262598e31SEd Tanous                                          "allowed in proxy mode");
753bd79bce8SPatrick Williams                         messages::resourceNotFound(asyncResp->res, action,
754bd79bce8SPatrick Williams                                                    resName);
75522db1728SEd Tanous 
75622db1728SEd Tanous                         return;
75722db1728SEd Tanous                     }
75822db1728SEd Tanous                     for (const auto& object : subtree)
75922db1728SEd Tanous                     {
760bd79bce8SPatrick Williams                         VmMode mode =
761bd79bce8SPatrick Williams                             parseObjectPathAndGetMode(object.first, resName);
7625880f0c5SBoleslaw Ogonczyk Makowski                         if (mode == VmMode::Legacy)
76322db1728SEd Tanous                         {
764bd79bce8SPatrick Williams                             validateParams(asyncResp, service, resName,
765bd79bce8SPatrick Williams                                            actionParams);
76622db1728SEd Tanous 
76722db1728SEd Tanous                             return;
76822db1728SEd Tanous                         }
76922db1728SEd Tanous                     }
77062598e31SEd Tanous                     BMCWEB_LOG_DEBUG("Parent item not found");
771bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res, "VirtualMedia",
772bd79bce8SPatrick Williams                                                resName);
7735eb468daSGeorge Liu                 });
7742b73119cSGeorge Liu         });
77596825bebSEd Tanous }
77622db1728SEd Tanous 
handleManagersVirtualMediaActionEject(crow::App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & managerName,const std::string & resName)77796825bebSEd Tanous inline void handleManagersVirtualMediaActionEject(
77896825bebSEd Tanous     crow::App& app, const crow::Request& req,
77922db1728SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
78096825bebSEd Tanous     const std::string& managerName, const std::string& resName)
78196825bebSEd Tanous {
7823ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
78345ca1b86SEd Tanous     {
78445ca1b86SEd Tanous         return;
78545ca1b86SEd Tanous     }
78679fdf63eSPrzemyslaw Czarnowski 
78779fdf63eSPrzemyslaw Czarnowski     constexpr std::string_view action = "VirtualMedia.EjectMedia";
78896825bebSEd Tanous     if (managerName != "bmc")
789107077deSPrzemyslaw Czarnowski     {
79079fdf63eSPrzemyslaw Czarnowski         messages::resourceNotFound(asyncResp->res, action, resName);
79122db1728SEd Tanous 
79222db1728SEd Tanous         return;
79322db1728SEd Tanous     }
79422db1728SEd Tanous 
7952b73119cSGeorge Liu     dbus::utility::getDbusObject(
7962b73119cSGeorge Liu         "/xyz/openbmc_project/VirtualMedia", {},
79779fdf63eSPrzemyslaw Czarnowski         [asyncResp, action,
7982b73119cSGeorge Liu          resName](const boost::system::error_code& ec2,
799b9d36b47SEd Tanous                   const dbus::utility::MapperGetObject& getObjectType) {
8008a592810SEd Tanous             if (ec2)
80122db1728SEd Tanous             {
802bd79bce8SPatrick Williams                 BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}",
803bd79bce8SPatrick Williams                                  ec2);
80422db1728SEd Tanous                 messages::internalError(asyncResp->res);
80522db1728SEd Tanous 
80622db1728SEd Tanous                 return;
80722db1728SEd Tanous             }
80822db1728SEd Tanous             std::string service = getObjectType.begin()->first;
80962598e31SEd Tanous             BMCWEB_LOG_DEBUG("GetObjectType: {}", service);
81022db1728SEd Tanous 
8115eb468daSGeorge Liu             sdbusplus::message::object_path path(
8125eb468daSGeorge Liu                 "/xyz/openbmc_project/VirtualMedia");
8135eb468daSGeorge Liu             dbus::utility::getManagedObjects(
8145eb468daSGeorge Liu                 service, path,
81579fdf63eSPrzemyslaw Czarnowski                 [resName, service, action,
81679fdf63eSPrzemyslaw Czarnowski                  asyncResp](const boost::system::error_code& ec,
81702cad96eSEd Tanous                             const dbus::utility::ManagedObjectType& subtree) {
81822db1728SEd Tanous                     if (ec)
81922db1728SEd Tanous                     {
82062598e31SEd Tanous                         BMCWEB_LOG_ERROR("ObjectMapper : No Service found");
821bd79bce8SPatrick Williams                         messages::resourceNotFound(asyncResp->res, action,
822bd79bce8SPatrick Williams                                                    resName);
82322db1728SEd Tanous                         return;
82422db1728SEd Tanous                     }
82522db1728SEd Tanous 
82622db1728SEd Tanous                     for (const auto& object : subtree)
82722db1728SEd Tanous                     {
828bd79bce8SPatrick Williams                         VmMode mode =
829bd79bce8SPatrick Williams                             parseObjectPathAndGetMode(object.first, resName);
830365a73f4SEd Tanous                         if (mode != VmMode::Invalid)
83122db1728SEd Tanous                         {
832365a73f4SEd Tanous                             doEjectAction(asyncResp, service, resName,
833365a73f4SEd Tanous                                           mode == VmMode::Legacy);
8345880f0c5SBoleslaw Ogonczyk Makowski                             return;
83522db1728SEd Tanous                         }
83622db1728SEd Tanous                     }
83762598e31SEd Tanous                     BMCWEB_LOG_DEBUG("Parent item not found");
838bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res, "VirtualMedia",
839bd79bce8SPatrick Williams                                                resName);
8405eb468daSGeorge Liu                 });
8412b73119cSGeorge Liu         });
84296825bebSEd Tanous }
84396825bebSEd Tanous 
handleManagersVirtualMediaCollectionGet(crow::App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & name)84496825bebSEd Tanous inline void handleManagersVirtualMediaCollectionGet(
84596825bebSEd Tanous     crow::App& app, const crow::Request& req,
84622db1728SEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
84796825bebSEd Tanous     const std::string& name)
84896825bebSEd Tanous {
8493ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
85045ca1b86SEd Tanous     {
85145ca1b86SEd Tanous         return;
85245ca1b86SEd Tanous     }
85322db1728SEd Tanous     if (name != "bmc")
85422db1728SEd Tanous     {
855002d39b4SEd Tanous         messages::resourceNotFound(asyncResp->res, "VirtualMedia", name);
856107077deSPrzemyslaw Czarnowski 
857107077deSPrzemyslaw Czarnowski         return;
858107077deSPrzemyslaw Czarnowski     }
859107077deSPrzemyslaw Czarnowski 
8608d1b46d7Szhanghch05     asyncResp->res.jsonValue["@odata.type"] =
861107077deSPrzemyslaw Czarnowski         "#VirtualMediaCollection.VirtualMediaCollection";
8628d1b46d7Szhanghch05     asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
863ef4c65b7SEd Tanous     asyncResp->res.jsonValue["@odata.id"] =
864ef4c65b7SEd Tanous         boost::urls::format("/redfish/v1/Managers/{}/VirtualMedia", name);
865107077deSPrzemyslaw Czarnowski 
8662b73119cSGeorge Liu     dbus::utility::getDbusObject(
8672b73119cSGeorge Liu         "/xyz/openbmc_project/VirtualMedia", {},
8682b73119cSGeorge Liu         [asyncResp, name](const boost::system::error_code& ec,
869b9d36b47SEd Tanous                           const dbus::utility::MapperGetObject& getObjectType) {
870107077deSPrzemyslaw Czarnowski             if (ec)
871107077deSPrzemyslaw Czarnowski             {
87262598e31SEd Tanous                 BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", ec);
873107077deSPrzemyslaw Czarnowski                 messages::internalError(asyncResp->res);
874107077deSPrzemyslaw Czarnowski 
875107077deSPrzemyslaw Czarnowski                 return;
876107077deSPrzemyslaw Czarnowski             }
877107077deSPrzemyslaw Czarnowski             std::string service = getObjectType.begin()->first;
87862598e31SEd Tanous             BMCWEB_LOG_DEBUG("GetObjectType: {}", service);
879107077deSPrzemyslaw Czarnowski 
880107077deSPrzemyslaw Czarnowski             getVmResourceList(asyncResp, service, name);
8812b73119cSGeorge Liu         });
88296825bebSEd Tanous }
883107077deSPrzemyslaw Czarnowski 
88496825bebSEd Tanous inline void
handleVirtualMediaGet(crow::App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & name,const std::string & resName)88596825bebSEd Tanous     handleVirtualMediaGet(crow::App& app, const crow::Request& req,
88622db1728SEd Tanous                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
88796825bebSEd Tanous                           const std::string& name, const std::string& resName)
88896825bebSEd Tanous {
8893ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
89045ca1b86SEd Tanous     {
89145ca1b86SEd Tanous         return;
89245ca1b86SEd Tanous     }
893107077deSPrzemyslaw Czarnowski     if (name != "bmc")
894107077deSPrzemyslaw Czarnowski     {
895002d39b4SEd Tanous         messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
896107077deSPrzemyslaw Czarnowski 
897107077deSPrzemyslaw Czarnowski         return;
898107077deSPrzemyslaw Czarnowski     }
899107077deSPrzemyslaw Czarnowski 
9002b73119cSGeorge Liu     dbus::utility::getDbusObject(
9012b73119cSGeorge Liu         "/xyz/openbmc_project/VirtualMedia", {},
902002d39b4SEd Tanous         [asyncResp, name,
9032b73119cSGeorge Liu          resName](const boost::system::error_code& ec,
904b9d36b47SEd Tanous                   const dbus::utility::MapperGetObject& getObjectType) {
905107077deSPrzemyslaw Czarnowski             if (ec)
906107077deSPrzemyslaw Czarnowski             {
90762598e31SEd Tanous                 BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", ec);
908107077deSPrzemyslaw Czarnowski                 messages::internalError(asyncResp->res);
909107077deSPrzemyslaw Czarnowski 
910107077deSPrzemyslaw Czarnowski                 return;
911107077deSPrzemyslaw Czarnowski             }
912107077deSPrzemyslaw Czarnowski             std::string service = getObjectType.begin()->first;
91362598e31SEd Tanous             BMCWEB_LOG_DEBUG("GetObjectType: {}", service);
914107077deSPrzemyslaw Czarnowski 
915107077deSPrzemyslaw Czarnowski             getVmData(asyncResp, service, name, resName);
9162b73119cSGeorge Liu         });
91796825bebSEd Tanous }
91896825bebSEd Tanous 
requestNBDVirtualMediaRoutes(App & app)91996825bebSEd Tanous inline void requestNBDVirtualMediaRoutes(App& app)
92096825bebSEd Tanous {
92196825bebSEd Tanous     BMCWEB_ROUTE(
92296825bebSEd Tanous         app,
92396825bebSEd Tanous         "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
92496825bebSEd Tanous         .privileges(redfish::privileges::postVirtualMedia)
92596825bebSEd Tanous         .methods(boost::beast::http::verb::post)(std::bind_front(
92696825bebSEd Tanous             handleManagersVirtualMediaActionInsertPost, std::ref(app)));
92796825bebSEd Tanous 
92896825bebSEd Tanous     BMCWEB_ROUTE(
92996825bebSEd Tanous         app,
93096825bebSEd Tanous         "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
93196825bebSEd Tanous         .privileges(redfish::privileges::postVirtualMedia)
93296825bebSEd Tanous         .methods(boost::beast::http::verb::post)(std::bind_front(
93396825bebSEd Tanous             handleManagersVirtualMediaActionEject, std::ref(app)));
93496825bebSEd Tanous 
93596825bebSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
93696825bebSEd Tanous         .privileges(redfish::privileges::getVirtualMediaCollection)
93796825bebSEd Tanous         .methods(boost::beast::http::verb::get)(std::bind_front(
93896825bebSEd Tanous             handleManagersVirtualMediaCollectionGet, std::ref(app)));
93996825bebSEd Tanous 
94096825bebSEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
94196825bebSEd Tanous         .privileges(redfish::privileges::getVirtualMedia)
94296825bebSEd Tanous         .methods(boost::beast::http::verb::get)(
94396825bebSEd Tanous             std::bind_front(handleVirtualMediaGet, std::ref(app)));
944107077deSPrzemyslaw Czarnowski }
945107077deSPrzemyslaw Czarnowski 
946107077deSPrzemyslaw Czarnowski } // namespace redfish
947