xref: /openbmc/bmcweb/features/redfish/lib/virtual_media.hpp (revision 0fda0f12bb9ae0604a083dfae419be38a1418913)
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 
187e860f15SJohn Edward Broadbent #include <app.hpp>
19107077deSPrzemyslaw Czarnowski #include <boost/container/flat_map.hpp>
20988fb7b2SAdrian Ambrożewicz #include <boost/process/async_pipe.hpp>
21988fb7b2SAdrian Ambrożewicz #include <boost/type_traits/has_dereference.hpp>
22107077deSPrzemyslaw Czarnowski #include <utils/json_utils.hpp>
23107077deSPrzemyslaw Czarnowski // for GetObjectType and ManagedObjectType
24ed398213SEd Tanous 
25e13c2760SPrzemyslaw Czarnowski #include <account_service.hpp>
269e319cf0SAnna Platash #include <boost/url/url_view.hpp>
27ed398213SEd Tanous #include <registries/privilege_registry.hpp>
28107077deSPrzemyslaw Czarnowski 
29107077deSPrzemyslaw Czarnowski namespace redfish
30107077deSPrzemyslaw Czarnowski {
319e319cf0SAnna Platash /**
329e319cf0SAnna Platash  * @brief Function extracts transfer protocol name from URI.
339e319cf0SAnna Platash  */
3422db1728SEd Tanous inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
359e319cf0SAnna Platash {
36d32c4fa9SEd Tanous     boost::urls::error_code ec;
37d32c4fa9SEd Tanous     boost::urls::url_view url =
38d32c4fa9SEd Tanous         boost::urls::parse_uri(boost::string_view(imageUri), ec);
39d32c4fa9SEd Tanous     if (ec)
409e319cf0SAnna Platash     {
41d32c4fa9SEd Tanous         return "None";
42d32c4fa9SEd Tanous     }
43d32c4fa9SEd Tanous     boost::string_view scheme = url.scheme();
449e319cf0SAnna Platash     if (scheme == "smb")
459e319cf0SAnna Platash     {
469e319cf0SAnna Platash         return "CIFS";
479e319cf0SAnna Platash     }
4822db1728SEd Tanous     if (scheme == "https")
499e319cf0SAnna Platash     {
509e319cf0SAnna Platash         return "HTTPS";
519e319cf0SAnna Platash     }
52d32c4fa9SEd Tanous 
539e319cf0SAnna Platash     return "None";
549e319cf0SAnna Platash }
55107077deSPrzemyslaw Czarnowski 
56107077deSPrzemyslaw Czarnowski /**
57107077deSPrzemyslaw Czarnowski  * @brief Read all known properties from VM object interfaces
58107077deSPrzemyslaw Czarnowski  */
5922db1728SEd Tanous inline void
608d1b46d7Szhanghch05     vmParseInterfaceObject(const DbusInterfaceType& interface,
618d1b46d7Szhanghch05                            const std::shared_ptr<bmcweb::AsyncResp>& aResp)
62107077deSPrzemyslaw Czarnowski {
63107077deSPrzemyslaw Czarnowski     const auto mountPointIface =
64107077deSPrzemyslaw Czarnowski         interface.find("xyz.openbmc_project.VirtualMedia.MountPoint");
65107077deSPrzemyslaw Czarnowski     if (mountPointIface == interface.cend())
66107077deSPrzemyslaw Czarnowski     {
67107077deSPrzemyslaw Czarnowski         BMCWEB_LOG_DEBUG << "Interface MountPoint not found";
68107077deSPrzemyslaw Czarnowski         return;
69107077deSPrzemyslaw Czarnowski     }
70107077deSPrzemyslaw Czarnowski 
71107077deSPrzemyslaw Czarnowski     const auto processIface =
72107077deSPrzemyslaw Czarnowski         interface.find("xyz.openbmc_project.VirtualMedia.Process");
73107077deSPrzemyslaw Czarnowski     if (processIface == interface.cend())
74107077deSPrzemyslaw Czarnowski     {
75107077deSPrzemyslaw Czarnowski         BMCWEB_LOG_DEBUG << "Interface Process not found";
76107077deSPrzemyslaw Czarnowski         return;
77107077deSPrzemyslaw Czarnowski     }
78107077deSPrzemyslaw Czarnowski 
79107077deSPrzemyslaw Czarnowski     const auto endpointIdProperty = mountPointIface->second.find("EndpointId");
80107077deSPrzemyslaw Czarnowski     if (endpointIdProperty == mountPointIface->second.cend())
81107077deSPrzemyslaw Czarnowski     {
82107077deSPrzemyslaw Czarnowski         BMCWEB_LOG_DEBUG << "Property EndpointId not found";
83107077deSPrzemyslaw Czarnowski         return;
84107077deSPrzemyslaw Czarnowski     }
85107077deSPrzemyslaw Czarnowski 
86107077deSPrzemyslaw Czarnowski     const auto activeProperty = processIface->second.find("Active");
87107077deSPrzemyslaw Czarnowski     if (activeProperty == processIface->second.cend())
88107077deSPrzemyslaw Czarnowski     {
89107077deSPrzemyslaw Czarnowski         BMCWEB_LOG_DEBUG << "Property Active not found";
90107077deSPrzemyslaw Czarnowski         return;
91107077deSPrzemyslaw Czarnowski     }
92107077deSPrzemyslaw Czarnowski 
93107077deSPrzemyslaw Czarnowski     const bool* activeValue = std::get_if<bool>(&activeProperty->second);
94107077deSPrzemyslaw Czarnowski     if (!activeValue)
95107077deSPrzemyslaw Czarnowski     {
96107077deSPrzemyslaw Czarnowski         BMCWEB_LOG_DEBUG << "Value Active not found";
97107077deSPrzemyslaw Czarnowski         return;
98107077deSPrzemyslaw Czarnowski     }
99107077deSPrzemyslaw Czarnowski 
100107077deSPrzemyslaw Czarnowski     const std::string* endpointIdValue =
101107077deSPrzemyslaw Czarnowski         std::get_if<std::string>(&endpointIdProperty->second);
102107077deSPrzemyslaw Czarnowski     if (endpointIdValue)
103107077deSPrzemyslaw Czarnowski     {
104107077deSPrzemyslaw Czarnowski         if (!endpointIdValue->empty())
105107077deSPrzemyslaw Czarnowski         {
106107077deSPrzemyslaw Czarnowski             // Proxy mode
107d04ba325SPrzemyslaw Czarnowski             aResp->res.jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
108d04ba325SPrzemyslaw Czarnowski                 *endpointIdValue;
109107077deSPrzemyslaw Czarnowski             aResp->res.jsonValue["TransferProtocolType"] = "OEM";
110107077deSPrzemyslaw Czarnowski             aResp->res.jsonValue["Inserted"] = *activeValue;
111107077deSPrzemyslaw Czarnowski             if (*activeValue == true)
112107077deSPrzemyslaw Czarnowski             {
113107077deSPrzemyslaw Czarnowski                 aResp->res.jsonValue["ConnectedVia"] = "Applet";
114107077deSPrzemyslaw Czarnowski             }
115107077deSPrzemyslaw Czarnowski         }
116107077deSPrzemyslaw Czarnowski         else
117107077deSPrzemyslaw Czarnowski         {
118107077deSPrzemyslaw Czarnowski             // Legacy mode
1199e319cf0SAnna Platash             for (const auto& property : mountPointIface->second)
1209e319cf0SAnna Platash             {
1219e319cf0SAnna Platash                 if (property.first == "ImageURL")
122107077deSPrzemyslaw Czarnowski                 {
123107077deSPrzemyslaw Czarnowski                     const std::string* imageUrlValue =
1249e319cf0SAnna Platash                         std::get_if<std::string>(&property.second);
125107077deSPrzemyslaw Czarnowski                     if (imageUrlValue && !imageUrlValue->empty())
126107077deSPrzemyslaw Czarnowski                     {
127da4784d8SPrzemyslaw Czarnowski                         std::filesystem::path filePath = *imageUrlValue;
128da4784d8SPrzemyslaw Czarnowski                         if (!filePath.has_filename())
129da4784d8SPrzemyslaw Czarnowski                         {
1309e319cf0SAnna Platash                             // this will handle https share, which not
1319e319cf0SAnna Platash                             // necessarily has to have filename given.
132da4784d8SPrzemyslaw Czarnowski                             aResp->res.jsonValue["ImageName"] = "";
133da4784d8SPrzemyslaw Czarnowski                         }
134da4784d8SPrzemyslaw Czarnowski                         else
135da4784d8SPrzemyslaw Czarnowski                         {
1369e319cf0SAnna Platash                             aResp->res.jsonValue["ImageName"] =
1379e319cf0SAnna Platash                                 filePath.filename();
138da4784d8SPrzemyslaw Czarnowski                         }
139da4784d8SPrzemyslaw Czarnowski 
140da4784d8SPrzemyslaw Czarnowski                         aResp->res.jsonValue["Image"] = *imageUrlValue;
141107077deSPrzemyslaw Czarnowski                         aResp->res.jsonValue["Inserted"] = *activeValue;
1429e319cf0SAnna Platash                         aResp->res.jsonValue["TransferProtocolType"] =
1439e319cf0SAnna Platash                             getTransferProtocolTypeFromUri(*imageUrlValue);
1449e319cf0SAnna Platash 
145107077deSPrzemyslaw Czarnowski                         if (*activeValue == true)
146107077deSPrzemyslaw Czarnowski                         {
147107077deSPrzemyslaw Czarnowski                             aResp->res.jsonValue["ConnectedVia"] = "URI";
148107077deSPrzemyslaw Czarnowski                         }
149107077deSPrzemyslaw Czarnowski                     }
150107077deSPrzemyslaw Czarnowski                 }
1519e319cf0SAnna Platash                 else if (property.first == "WriteProtected")
1529e319cf0SAnna Platash                 {
1539e319cf0SAnna Platash                     const bool* writeProtectedValue =
1549e319cf0SAnna Platash                         std::get_if<bool>(&property.second);
1559e319cf0SAnna Platash                     if (writeProtectedValue)
1569e319cf0SAnna Platash                     {
1579e319cf0SAnna Platash                         aResp->res.jsonValue["WriteProtected"] =
1589e319cf0SAnna Platash                             *writeProtectedValue;
1599e319cf0SAnna Platash                     }
1609e319cf0SAnna Platash                 }
1619e319cf0SAnna Platash             }
162107077deSPrzemyslaw Czarnowski         }
163107077deSPrzemyslaw Czarnowski     }
164107077deSPrzemyslaw Czarnowski }
165107077deSPrzemyslaw Czarnowski 
166107077deSPrzemyslaw Czarnowski /**
167107077deSPrzemyslaw Czarnowski  * @brief Fill template for Virtual Media Item.
168107077deSPrzemyslaw Czarnowski  */
16922db1728SEd Tanous inline nlohmann::json vmItemTemplate(const std::string& name,
170107077deSPrzemyslaw Czarnowski                                      const std::string& resName)
171107077deSPrzemyslaw Czarnowski {
172107077deSPrzemyslaw Czarnowski     nlohmann::json item;
17322db1728SEd Tanous 
17422db1728SEd Tanous     std::string id = "/redfish/v1/Managers/";
17522db1728SEd Tanous     id += name;
17622db1728SEd Tanous     id += "/VirtualMedia/";
17722db1728SEd Tanous     id += resName;
17822db1728SEd Tanous     item["@odata.id"] = std::move(id);
17922db1728SEd Tanous 
180d04ba325SPrzemyslaw Czarnowski     item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
181107077deSPrzemyslaw Czarnowski     item["Name"] = "Virtual Removable Media";
182107077deSPrzemyslaw Czarnowski     item["Id"] = resName;
183107077deSPrzemyslaw Czarnowski     item["WriteProtected"] = true;
184107077deSPrzemyslaw Czarnowski     item["MediaTypes"] = {"CD", "USBStick"};
185107077deSPrzemyslaw Czarnowski     item["TransferMethod"] = "Stream";
186d04ba325SPrzemyslaw Czarnowski     item["Oem"]["OpenBMC"]["@odata.type"] =
187d04ba325SPrzemyslaw Czarnowski         "#OemVirtualMedia.v1_0_0.VirtualMedia";
188107077deSPrzemyslaw Czarnowski 
189107077deSPrzemyslaw Czarnowski     return item;
190107077deSPrzemyslaw Czarnowski }
191107077deSPrzemyslaw Czarnowski 
192107077deSPrzemyslaw Czarnowski /**
193107077deSPrzemyslaw Czarnowski  *  @brief Fills collection data
194107077deSPrzemyslaw Czarnowski  */
19522db1728SEd Tanous inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
196107077deSPrzemyslaw Czarnowski                               const std::string& service,
197107077deSPrzemyslaw Czarnowski                               const std::string& name)
198107077deSPrzemyslaw Czarnowski {
199107077deSPrzemyslaw Czarnowski     BMCWEB_LOG_DEBUG << "Get available Virtual Media resources.";
200107077deSPrzemyslaw Czarnowski     crow::connections::systemBus->async_method_call(
201107077deSPrzemyslaw Czarnowski         [name, aResp{std::move(aResp)}](const boost::system::error_code ec,
202107077deSPrzemyslaw Czarnowski                                         ManagedObjectType& subtree) {
203107077deSPrzemyslaw Czarnowski             if (ec)
204107077deSPrzemyslaw Czarnowski             {
205107077deSPrzemyslaw Czarnowski                 BMCWEB_LOG_DEBUG << "DBUS response error";
206107077deSPrzemyslaw Czarnowski                 return;
207107077deSPrzemyslaw Czarnowski             }
208107077deSPrzemyslaw Czarnowski             nlohmann::json& members = aResp->res.jsonValue["Members"];
209107077deSPrzemyslaw Czarnowski             members = nlohmann::json::array();
210107077deSPrzemyslaw Czarnowski 
211107077deSPrzemyslaw Czarnowski             for (const auto& object : subtree)
212107077deSPrzemyslaw Czarnowski             {
213107077deSPrzemyslaw Czarnowski                 nlohmann::json item;
2142dfd18efSEd Tanous                 std::string path = object.first.filename();
2152dfd18efSEd Tanous                 if (path.empty())
216107077deSPrzemyslaw Czarnowski                 {
217107077deSPrzemyslaw Czarnowski                     continue;
218107077deSPrzemyslaw Czarnowski                 }
219107077deSPrzemyslaw Czarnowski 
22022db1728SEd Tanous                 std::string id = "/redfish/v1/Managers/";
22122db1728SEd Tanous                 id += name;
22222db1728SEd Tanous                 id += "/VirtualMedia/";
22322db1728SEd Tanous                 id += path;
224107077deSPrzemyslaw Czarnowski 
22522db1728SEd Tanous                 item["@odata.id"] = std::move(id);
226107077deSPrzemyslaw Czarnowski                 members.emplace_back(std::move(item));
227107077deSPrzemyslaw Czarnowski             }
228107077deSPrzemyslaw Czarnowski             aResp->res.jsonValue["Members@odata.count"] = members.size();
229107077deSPrzemyslaw Czarnowski         },
230107077deSPrzemyslaw Czarnowski         service, "/xyz/openbmc_project/VirtualMedia",
231107077deSPrzemyslaw Czarnowski         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
232107077deSPrzemyslaw Czarnowski }
233107077deSPrzemyslaw Czarnowski 
234107077deSPrzemyslaw Czarnowski /**
235107077deSPrzemyslaw Czarnowski  *  @brief Fills data for specific resource
236107077deSPrzemyslaw Czarnowski  */
23722db1728SEd Tanous inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
238107077deSPrzemyslaw Czarnowski                       const std::string& service, const std::string& name,
239107077deSPrzemyslaw Czarnowski                       const std::string& resName)
240107077deSPrzemyslaw Czarnowski {
241107077deSPrzemyslaw Czarnowski     BMCWEB_LOG_DEBUG << "Get Virtual Media resource data.";
242107077deSPrzemyslaw Czarnowski 
243107077deSPrzemyslaw Czarnowski     crow::connections::systemBus->async_method_call(
244107077deSPrzemyslaw Czarnowski         [resName, name, aResp](const boost::system::error_code ec,
245107077deSPrzemyslaw Czarnowski                                ManagedObjectType& subtree) {
246107077deSPrzemyslaw Czarnowski             if (ec)
247107077deSPrzemyslaw Czarnowski             {
248107077deSPrzemyslaw Czarnowski                 BMCWEB_LOG_DEBUG << "DBUS response error";
249e13c2760SPrzemyslaw Czarnowski 
250107077deSPrzemyslaw Czarnowski                 return;
251107077deSPrzemyslaw Czarnowski             }
252107077deSPrzemyslaw Czarnowski 
253107077deSPrzemyslaw Czarnowski             for (auto& item : subtree)
254107077deSPrzemyslaw Czarnowski             {
2552dfd18efSEd Tanous                 std::string thispath = item.first.filename();
2562dfd18efSEd Tanous                 if (thispath.empty())
257107077deSPrzemyslaw Czarnowski                 {
258107077deSPrzemyslaw Czarnowski                     continue;
259107077deSPrzemyslaw Czarnowski                 }
260107077deSPrzemyslaw Czarnowski 
2612dfd18efSEd Tanous                 if (thispath != resName)
262107077deSPrzemyslaw Czarnowski                 {
263107077deSPrzemyslaw Czarnowski                     continue;
264107077deSPrzemyslaw Czarnowski                 }
265107077deSPrzemyslaw Czarnowski 
2661a6258dcSPrzemyslaw Czarnowski                 // "Legacy"/"Proxy"
2671a6258dcSPrzemyslaw Czarnowski                 auto mode = item.first.parent_path();
2681a6258dcSPrzemyslaw Czarnowski                 // "VirtualMedia"
2691a6258dcSPrzemyslaw Czarnowski                 auto type = mode.parent_path();
2701a6258dcSPrzemyslaw Czarnowski                 if (mode.filename().empty() || type.filename().empty())
2711a6258dcSPrzemyslaw Czarnowski                 {
2721a6258dcSPrzemyslaw Czarnowski                     continue;
2731a6258dcSPrzemyslaw Czarnowski                 }
2741a6258dcSPrzemyslaw Czarnowski 
2751a6258dcSPrzemyslaw Czarnowski                 if (type.filename() != "VirtualMedia")
2761a6258dcSPrzemyslaw Czarnowski                 {
2771a6258dcSPrzemyslaw Czarnowski                     continue;
2781a6258dcSPrzemyslaw Czarnowski                 }
2791a6258dcSPrzemyslaw Czarnowski 
280107077deSPrzemyslaw Czarnowski                 aResp->res.jsonValue = vmItemTemplate(name, resName);
28122db1728SEd Tanous                 std::string actionsId = "/redfish/v1/Managers/";
28222db1728SEd Tanous                 actionsId += name;
28322db1728SEd Tanous                 actionsId += "/VirtualMedia/";
28422db1728SEd Tanous                 actionsId += resName;
28522db1728SEd Tanous                 actionsId += "/Actions";
286107077deSPrzemyslaw Czarnowski 
287e13c2760SPrzemyslaw Czarnowski                 // Check if dbus path is Legacy type
2881a6258dcSPrzemyslaw Czarnowski                 if (mode.filename() == "Legacy")
289e13c2760SPrzemyslaw Czarnowski                 {
290e13c2760SPrzemyslaw Czarnowski                     aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
291e13c2760SPrzemyslaw Czarnowski                                         ["target"] =
29222db1728SEd Tanous                         actionsId + "/VirtualMedia.InsertMedia";
293e13c2760SPrzemyslaw Czarnowski                 }
294e13c2760SPrzemyslaw Czarnowski 
295107077deSPrzemyslaw Czarnowski                 vmParseInterfaceObject(item.second, aResp);
296107077deSPrzemyslaw Czarnowski 
297e13c2760SPrzemyslaw Czarnowski                 aResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"]
298e13c2760SPrzemyslaw Czarnowski                                     ["target"] =
29922db1728SEd Tanous                     actionsId + "/VirtualMedia.EjectMedia";
300e13c2760SPrzemyslaw Czarnowski 
301107077deSPrzemyslaw Czarnowski                 return;
302107077deSPrzemyslaw Czarnowski             }
303107077deSPrzemyslaw Czarnowski 
304107077deSPrzemyslaw Czarnowski             messages::resourceNotFound(
305d04ba325SPrzemyslaw Czarnowski                 aResp->res, "#VirtualMedia.v1_3_0.VirtualMedia", resName);
306107077deSPrzemyslaw Czarnowski         },
307107077deSPrzemyslaw Czarnowski         service, "/xyz/openbmc_project/VirtualMedia",
308107077deSPrzemyslaw Czarnowski         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
309107077deSPrzemyslaw Czarnowski }
310107077deSPrzemyslaw Czarnowski 
311e13c2760SPrzemyslaw Czarnowski /**
312c6f4e017SAgata Olender  * @brief Transfer protocols supported for InsertMedia action.
313c6f4e017SAgata Olender  *
314c6f4e017SAgata Olender  */
315c6f4e017SAgata Olender enum class TransferProtocol
316c6f4e017SAgata Olender {
317c6f4e017SAgata Olender     https,
318c6f4e017SAgata Olender     smb,
319c6f4e017SAgata Olender     invalid
320c6f4e017SAgata Olender };
321c6f4e017SAgata Olender 
322c6f4e017SAgata Olender /**
323c6f4e017SAgata Olender  * @brief Function extracts transfer protocol type from URI.
324c6f4e017SAgata Olender  *
325c6f4e017SAgata Olender  */
32622db1728SEd Tanous inline std::optional<TransferProtocol>
327c6f4e017SAgata Olender     getTransferProtocolFromUri(const std::string& imageUri)
328c6f4e017SAgata Olender {
329d32c4fa9SEd Tanous     boost::urls::error_code ec;
330d32c4fa9SEd Tanous     boost::urls::url_view url =
331d32c4fa9SEd Tanous         boost::urls::parse_uri(boost::string_view(imageUri), ec);
332d32c4fa9SEd Tanous     if (ec)
3339e319cf0SAnna Platash     {
334d32c4fa9SEd Tanous         return {};
335d32c4fa9SEd Tanous     }
336d32c4fa9SEd Tanous 
337d32c4fa9SEd Tanous     boost::string_view scheme = url.scheme();
3389e319cf0SAnna Platash     if (scheme == "smb")
339c6f4e017SAgata Olender     {
340c6f4e017SAgata Olender         return TransferProtocol::smb;
341c6f4e017SAgata Olender     }
34281ce609eSEd Tanous     if (scheme == "https")
343c6f4e017SAgata Olender     {
344c6f4e017SAgata Olender         return TransferProtocol::https;
345c6f4e017SAgata Olender     }
34622db1728SEd Tanous     if (!scheme.empty())
347c6f4e017SAgata Olender     {
348c6f4e017SAgata Olender         return TransferProtocol::invalid;
349c6f4e017SAgata Olender     }
3509e319cf0SAnna Platash 
3519e319cf0SAnna Platash     return {};
352c6f4e017SAgata Olender }
353c6f4e017SAgata Olender 
354c6f4e017SAgata Olender /**
355c6f4e017SAgata Olender  * @brief Function convert transfer protocol from string param.
356c6f4e017SAgata Olender  *
357c6f4e017SAgata Olender  */
35822db1728SEd Tanous inline 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  */
38322db1728SEd Tanous inline 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  */
40422db1728SEd Tanous inline bool
40522db1728SEd Tanous     validateParams(crow::Response& res, std::string& imageUrl,
406c6f4e017SAgata Olender                    const std::optional<bool>& inserted,
407c6f4e017SAgata Olender                    const std::optional<std::string>& transferMethod,
408c6f4e017SAgata Olender                    const std::optional<std::string>& transferProtocolType)
409c6f4e017SAgata Olender {
410c6f4e017SAgata Olender     BMCWEB_LOG_DEBUG << "Validation started";
411c6f4e017SAgata Olender     // required param imageUrl must not be empty
412c6f4e017SAgata Olender     if (imageUrl.empty())
413c6f4e017SAgata Olender     {
414c6f4e017SAgata Olender         BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
415c6f4e017SAgata Olender 
41622db1728SEd Tanous         messages::propertyValueFormatError(res, "<empty>", "Image");
417c6f4e017SAgata Olender 
418c6f4e017SAgata Olender         return false;
419c6f4e017SAgata Olender     }
420c6f4e017SAgata Olender 
421c6f4e017SAgata Olender     // optional param inserted must be true
422c6f4e017SAgata Olender     if ((inserted != std::nullopt) && (*inserted != true))
423c6f4e017SAgata Olender     {
424c6f4e017SAgata Olender         BMCWEB_LOG_ERROR
425c6f4e017SAgata Olender             << "Request action optional parameter Inserted must be true.";
426c6f4e017SAgata Olender 
42722db1728SEd Tanous         messages::actionParameterNotSupported(res, "Inserted", "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 
43822db1728SEd Tanous         messages::actionParameterNotSupported(res, "TransferMethod",
43922db1728SEd Tanous                                               "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 
45722db1728SEd Tanous         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 
46922db1728SEd Tanous         messages::propertyValueNotInList(res, *transferProtocolType,
47022db1728SEd Tanous                                          "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 
48222db1728SEd Tanous         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 
49922db1728SEd Tanous             messages::actionParameterValueTypeError(res, *transferProtocolType,
50022db1728SEd Tanous                                                     "TransferProtocolType",
50122db1728SEd Tanous                                                     "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     {
51122db1728SEd Tanous         imageUrl =
51222db1728SEd Tanous             getUriWithTransferProtocol(imageUrl, *paramTransferProtocolType);
513c6f4e017SAgata Olender     }
514c6f4e017SAgata Olender 
515c6f4e017SAgata Olender     return true;
516c6f4e017SAgata Olender }
517c6f4e017SAgata Olender 
5181214b7e7SGunnar Mills template <typename T>
5191214b7e7SGunnar Mills static void secureCleanup(T& value)
520988fb7b2SAdrian Ambrożewicz {
521988fb7b2SAdrian Ambrożewicz     auto raw = const_cast<typename T::value_type*>(value.data());
522988fb7b2SAdrian Ambrożewicz     explicit_bzero(raw, value.size() * sizeof(*raw));
523988fb7b2SAdrian Ambrożewicz }
524988fb7b2SAdrian Ambrożewicz 
525988fb7b2SAdrian Ambrożewicz class Credentials
526988fb7b2SAdrian Ambrożewicz {
527988fb7b2SAdrian Ambrożewicz   public:
528988fb7b2SAdrian Ambrożewicz     Credentials(std::string&& user, std::string&& password) :
529988fb7b2SAdrian Ambrożewicz         userBuf(std::move(user)), passBuf(std::move(password))
5301214b7e7SGunnar Mills     {}
531988fb7b2SAdrian Ambrożewicz 
532988fb7b2SAdrian Ambrożewicz     ~Credentials()
533988fb7b2SAdrian Ambrożewicz     {
534988fb7b2SAdrian Ambrożewicz         secureCleanup(userBuf);
535988fb7b2SAdrian Ambrożewicz         secureCleanup(passBuf);
536988fb7b2SAdrian Ambrożewicz     }
537988fb7b2SAdrian Ambrożewicz 
538988fb7b2SAdrian Ambrożewicz     const std::string& user()
539988fb7b2SAdrian Ambrożewicz     {
540988fb7b2SAdrian Ambrożewicz         return userBuf;
541988fb7b2SAdrian Ambrożewicz     }
542988fb7b2SAdrian Ambrożewicz 
543988fb7b2SAdrian Ambrożewicz     const std::string& password()
544988fb7b2SAdrian Ambrożewicz     {
545988fb7b2SAdrian Ambrożewicz         return passBuf;
546988fb7b2SAdrian Ambrożewicz     }
547988fb7b2SAdrian Ambrożewicz 
548988fb7b2SAdrian Ambrożewicz     Credentials() = delete;
549988fb7b2SAdrian Ambrożewicz     Credentials(const Credentials&) = delete;
550988fb7b2SAdrian Ambrożewicz     Credentials& operator=(const Credentials&) = delete;
551988fb7b2SAdrian Ambrożewicz 
55222db1728SEd Tanous   private:
553988fb7b2SAdrian Ambrożewicz     std::string userBuf;
554988fb7b2SAdrian Ambrożewicz     std::string passBuf;
555988fb7b2SAdrian Ambrożewicz };
556988fb7b2SAdrian Ambrożewicz 
557988fb7b2SAdrian Ambrożewicz class CredentialsProvider
558988fb7b2SAdrian Ambrożewicz {
559988fb7b2SAdrian Ambrożewicz   public:
5601214b7e7SGunnar Mills     template <typename T>
5611214b7e7SGunnar Mills     struct Deleter
562988fb7b2SAdrian Ambrożewicz     {
563988fb7b2SAdrian Ambrożewicz         void operator()(T* buff) const
564988fb7b2SAdrian Ambrożewicz         {
565988fb7b2SAdrian Ambrożewicz             if (buff)
566988fb7b2SAdrian Ambrożewicz             {
567988fb7b2SAdrian Ambrożewicz                 secureCleanup(*buff);
568988fb7b2SAdrian Ambrożewicz                 delete buff;
569988fb7b2SAdrian Ambrożewicz             }
570988fb7b2SAdrian Ambrożewicz         }
571988fb7b2SAdrian Ambrożewicz     };
572988fb7b2SAdrian Ambrożewicz 
573988fb7b2SAdrian Ambrożewicz     using Buffer = std::vector<char>;
574988fb7b2SAdrian Ambrożewicz     using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
575988fb7b2SAdrian Ambrożewicz     // Using explicit definition instead of std::function to avoid implicit
576988fb7b2SAdrian Ambrożewicz     // conversions eg. stack copy instead of reference
577988fb7b2SAdrian Ambrożewicz     using FormatterFunc = void(const std::string& username,
578988fb7b2SAdrian Ambrożewicz                                const std::string& password, Buffer& dest);
579988fb7b2SAdrian Ambrożewicz 
580988fb7b2SAdrian Ambrożewicz     CredentialsProvider(std::string&& user, std::string&& password) :
581988fb7b2SAdrian Ambrożewicz         credentials(std::move(user), std::move(password))
5821214b7e7SGunnar Mills     {}
583988fb7b2SAdrian Ambrożewicz 
584988fb7b2SAdrian Ambrożewicz     const std::string& user()
585988fb7b2SAdrian Ambrożewicz     {
586988fb7b2SAdrian Ambrożewicz         return credentials.user();
587988fb7b2SAdrian Ambrożewicz     }
588988fb7b2SAdrian Ambrożewicz 
589988fb7b2SAdrian Ambrożewicz     const std::string& password()
590988fb7b2SAdrian Ambrożewicz     {
591988fb7b2SAdrian Ambrożewicz         return credentials.password();
592988fb7b2SAdrian Ambrożewicz     }
593988fb7b2SAdrian Ambrożewicz 
59481ce609eSEd Tanous     SecureBuffer pack(FormatterFunc formatter)
595988fb7b2SAdrian Ambrożewicz     {
596988fb7b2SAdrian Ambrożewicz         SecureBuffer packed{new Buffer{}};
597988fb7b2SAdrian Ambrożewicz         if (formatter)
598988fb7b2SAdrian Ambrożewicz         {
599988fb7b2SAdrian Ambrożewicz             formatter(credentials.user(), credentials.password(), *packed);
600988fb7b2SAdrian Ambrożewicz         }
601988fb7b2SAdrian Ambrożewicz 
602988fb7b2SAdrian Ambrożewicz         return packed;
603988fb7b2SAdrian Ambrożewicz     }
604988fb7b2SAdrian Ambrożewicz 
605988fb7b2SAdrian Ambrożewicz   private:
606988fb7b2SAdrian Ambrożewicz     Credentials credentials;
607988fb7b2SAdrian Ambrożewicz };
608988fb7b2SAdrian Ambrożewicz 
609988fb7b2SAdrian Ambrożewicz // Wrapper for boost::async_pipe ensuring proper pipe cleanup
6101214b7e7SGunnar Mills template <typename Buffer>
6111214b7e7SGunnar Mills class Pipe
612988fb7b2SAdrian Ambrożewicz {
613988fb7b2SAdrian Ambrożewicz   public:
614988fb7b2SAdrian Ambrożewicz     using unix_fd = sdbusplus::message::unix_fd;
615988fb7b2SAdrian Ambrożewicz 
616988fb7b2SAdrian Ambrożewicz     Pipe(boost::asio::io_context& io, Buffer&& buffer) :
617988fb7b2SAdrian Ambrożewicz         impl(io), buffer{std::move(buffer)}
6181214b7e7SGunnar Mills     {}
619988fb7b2SAdrian Ambrożewicz 
620988fb7b2SAdrian Ambrożewicz     ~Pipe()
621988fb7b2SAdrian Ambrożewicz     {
622988fb7b2SAdrian Ambrożewicz         // Named pipe needs to be explicitly removed
623988fb7b2SAdrian Ambrożewicz         impl.close();
624988fb7b2SAdrian Ambrożewicz     }
625988fb7b2SAdrian Ambrożewicz 
626988fb7b2SAdrian Ambrożewicz     unix_fd fd()
627988fb7b2SAdrian Ambrożewicz     {
628988fb7b2SAdrian Ambrożewicz         return unix_fd{impl.native_source()};
629988fb7b2SAdrian Ambrożewicz     }
630988fb7b2SAdrian Ambrożewicz 
631988fb7b2SAdrian Ambrożewicz     template <typename WriteHandler>
63281ce609eSEd Tanous     void asyncWrite(WriteHandler&& handler)
633988fb7b2SAdrian Ambrożewicz     {
634988fb7b2SAdrian Ambrożewicz         impl.async_write_some(data(), std::forward<WriteHandler>(handler));
635988fb7b2SAdrian Ambrożewicz     }
636988fb7b2SAdrian Ambrożewicz 
637988fb7b2SAdrian Ambrożewicz   private:
638988fb7b2SAdrian Ambrożewicz     // Specialization for pointer types
639988fb7b2SAdrian Ambrożewicz     template <typename B = Buffer>
640988fb7b2SAdrian Ambrożewicz     typename std::enable_if<boost::has_dereference<B>::value,
641988fb7b2SAdrian Ambrożewicz                             boost::asio::const_buffer>::type
642988fb7b2SAdrian Ambrożewicz         data()
643988fb7b2SAdrian Ambrożewicz     {
644988fb7b2SAdrian Ambrożewicz         return boost::asio::buffer(*buffer);
645988fb7b2SAdrian Ambrożewicz     }
646988fb7b2SAdrian Ambrożewicz 
647988fb7b2SAdrian Ambrożewicz     template <typename B = Buffer>
648988fb7b2SAdrian Ambrożewicz     typename std::enable_if<!boost::has_dereference<B>::value,
649988fb7b2SAdrian Ambrożewicz                             boost::asio::const_buffer>::type
650988fb7b2SAdrian Ambrożewicz         data()
651988fb7b2SAdrian Ambrożewicz     {
652988fb7b2SAdrian Ambrożewicz         return boost::asio::buffer(buffer);
653988fb7b2SAdrian Ambrożewicz     }
654988fb7b2SAdrian Ambrożewicz 
655988fb7b2SAdrian Ambrożewicz     const std::string name;
656988fb7b2SAdrian Ambrożewicz     boost::process::async_pipe impl;
657988fb7b2SAdrian Ambrożewicz     Buffer buffer;
658988fb7b2SAdrian Ambrożewicz };
659988fb7b2SAdrian Ambrożewicz 
660e13c2760SPrzemyslaw Czarnowski /**
661e13c2760SPrzemyslaw Czarnowski  * @brief Function transceives data with dbus directly.
662e13c2760SPrzemyslaw Czarnowski  *
663e13c2760SPrzemyslaw Czarnowski  * All BMC state properties will be retrieved before sending reset request.
664e13c2760SPrzemyslaw Czarnowski  */
66522db1728SEd Tanous inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
666e13c2760SPrzemyslaw Czarnowski                             const std::string& service, const std::string& name,
667988fb7b2SAdrian Ambrożewicz                             const std::string& imageUrl, const bool rw,
668988fb7b2SAdrian Ambrożewicz                             std::string&& userName, std::string&& password)
669e13c2760SPrzemyslaw Czarnowski {
670988fb7b2SAdrian Ambrożewicz     using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
671988fb7b2SAdrian Ambrożewicz     constexpr const size_t secretLimit = 1024;
672988fb7b2SAdrian Ambrożewicz 
673988fb7b2SAdrian Ambrożewicz     std::shared_ptr<SecurePipe> secretPipe;
674988fb7b2SAdrian Ambrożewicz     std::variant<int, SecurePipe::unix_fd> unixFd = -1;
675988fb7b2SAdrian Ambrożewicz 
676988fb7b2SAdrian Ambrożewicz     if (!userName.empty() || !password.empty())
677988fb7b2SAdrian Ambrożewicz     {
678988fb7b2SAdrian Ambrożewicz         // Encapsulate in safe buffer
679988fb7b2SAdrian Ambrożewicz         CredentialsProvider credentials(std::move(userName),
680988fb7b2SAdrian Ambrożewicz                                         std::move(password));
681988fb7b2SAdrian Ambrożewicz 
682988fb7b2SAdrian Ambrożewicz         // Payload must contain data + NULL delimiters
683988fb7b2SAdrian Ambrożewicz         if (credentials.user().size() + credentials.password().size() + 2 >
684988fb7b2SAdrian Ambrożewicz             secretLimit)
685988fb7b2SAdrian Ambrożewicz         {
686988fb7b2SAdrian Ambrożewicz             BMCWEB_LOG_ERROR << "Credentials too long to handle";
687988fb7b2SAdrian Ambrożewicz             messages::unrecognizedRequestBody(asyncResp->res);
688988fb7b2SAdrian Ambrożewicz             return;
689988fb7b2SAdrian Ambrożewicz         }
690988fb7b2SAdrian Ambrożewicz 
691988fb7b2SAdrian Ambrożewicz         // Pack secret
69222db1728SEd Tanous         auto secret = credentials.pack(
69322db1728SEd Tanous             [](const auto& user, const auto& pass, auto& buff) {
694988fb7b2SAdrian Ambrożewicz                 std::copy(user.begin(), user.end(), std::back_inserter(buff));
695988fb7b2SAdrian Ambrożewicz                 buff.push_back('\0');
696988fb7b2SAdrian Ambrożewicz                 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
697988fb7b2SAdrian Ambrożewicz                 buff.push_back('\0');
698988fb7b2SAdrian Ambrożewicz             });
699988fb7b2SAdrian Ambrożewicz 
700988fb7b2SAdrian Ambrożewicz         // Open pipe
701988fb7b2SAdrian Ambrożewicz         secretPipe = std::make_shared<SecurePipe>(
70222db1728SEd Tanous             crow::connections::systemBus->get_io_context(), std::move(secret));
703988fb7b2SAdrian Ambrożewicz         unixFd = secretPipe->fd();
704988fb7b2SAdrian Ambrożewicz 
705988fb7b2SAdrian Ambrożewicz         // Pass secret over pipe
70681ce609eSEd Tanous         secretPipe->asyncWrite(
707f5b16f03SVikram Bodireddy             [asyncResp](const boost::system::error_code& ec, std::size_t) {
708988fb7b2SAdrian Ambrożewicz                 if (ec)
709988fb7b2SAdrian Ambrożewicz                 {
710988fb7b2SAdrian Ambrożewicz                     BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
711988fb7b2SAdrian Ambrożewicz                     messages::internalError(asyncResp->res);
712988fb7b2SAdrian Ambrożewicz                 }
713988fb7b2SAdrian Ambrożewicz             });
714988fb7b2SAdrian Ambrożewicz     }
715988fb7b2SAdrian Ambrożewicz 
716e13c2760SPrzemyslaw Czarnowski     crow::connections::systemBus->async_method_call(
717988fb7b2SAdrian Ambrożewicz         [asyncResp, secretPipe](const boost::system::error_code ec,
718988fb7b2SAdrian Ambrożewicz                                 bool success) {
719e13c2760SPrzemyslaw Czarnowski             if (ec)
720e13c2760SPrzemyslaw Czarnowski             {
721e13c2760SPrzemyslaw Czarnowski                 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
722e13c2760SPrzemyslaw Czarnowski                 messages::internalError(asyncResp->res);
723d6da5bebSAdrian Ambrożewicz             }
724d6da5bebSAdrian Ambrożewicz             else if (!success)
725d6da5bebSAdrian Ambrożewicz             {
726d6da5bebSAdrian Ambrożewicz                 BMCWEB_LOG_ERROR << "Service responded with error";
727d6da5bebSAdrian Ambrożewicz                 messages::generalError(asyncResp->res);
728e13c2760SPrzemyslaw Czarnowski             }
729e13c2760SPrzemyslaw Czarnowski         },
730e13c2760SPrzemyslaw Czarnowski         service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
731988fb7b2SAdrian Ambrożewicz         "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
732988fb7b2SAdrian Ambrożewicz         unixFd);
733e13c2760SPrzemyslaw Czarnowski }
734e13c2760SPrzemyslaw Czarnowski 
735e13c2760SPrzemyslaw Czarnowski /**
736e13c2760SPrzemyslaw Czarnowski  * @brief Function transceives data with dbus directly.
737e13c2760SPrzemyslaw Czarnowski  *
738e13c2760SPrzemyslaw Czarnowski  * All BMC state properties will be retrieved before sending reset request.
739e13c2760SPrzemyslaw Czarnowski  */
74022db1728SEd Tanous inline void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
741e13c2760SPrzemyslaw Czarnowski                        const std::string& service, const std::string& name,
742e13c2760SPrzemyslaw Czarnowski                        bool legacy)
743e13c2760SPrzemyslaw Czarnowski {
744e13c2760SPrzemyslaw Czarnowski 
745e13c2760SPrzemyslaw Czarnowski     // Legacy mount requires parameter with image
746e13c2760SPrzemyslaw Czarnowski     if (legacy)
747e13c2760SPrzemyslaw Czarnowski     {
748e13c2760SPrzemyslaw Czarnowski         crow::connections::systemBus->async_method_call(
749e13c2760SPrzemyslaw Czarnowski             [asyncResp](const boost::system::error_code ec) {
750e13c2760SPrzemyslaw Czarnowski                 if (ec)
751e13c2760SPrzemyslaw Czarnowski                 {
752e13c2760SPrzemyslaw Czarnowski                     BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
753e13c2760SPrzemyslaw Czarnowski 
754e13c2760SPrzemyslaw Czarnowski                     messages::internalError(asyncResp->res);
755e13c2760SPrzemyslaw Czarnowski                     return;
756e13c2760SPrzemyslaw Czarnowski                 }
757e13c2760SPrzemyslaw Czarnowski             },
758e13c2760SPrzemyslaw Czarnowski             service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
759e13c2760SPrzemyslaw Czarnowski             "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
760e13c2760SPrzemyslaw Czarnowski     }
761e13c2760SPrzemyslaw Czarnowski     else // proxy
762e13c2760SPrzemyslaw Czarnowski     {
763e13c2760SPrzemyslaw Czarnowski         crow::connections::systemBus->async_method_call(
764e13c2760SPrzemyslaw Czarnowski             [asyncResp](const boost::system::error_code ec) {
765e13c2760SPrzemyslaw Czarnowski                 if (ec)
766e13c2760SPrzemyslaw Czarnowski                 {
767e13c2760SPrzemyslaw Czarnowski                     BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
768e13c2760SPrzemyslaw Czarnowski 
769e13c2760SPrzemyslaw Czarnowski                     messages::internalError(asyncResp->res);
770e13c2760SPrzemyslaw Czarnowski                     return;
771e13c2760SPrzemyslaw Czarnowski                 }
772e13c2760SPrzemyslaw Czarnowski             },
773e13c2760SPrzemyslaw Czarnowski             service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
774e13c2760SPrzemyslaw Czarnowski             "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
775e13c2760SPrzemyslaw Czarnowski     }
776e13c2760SPrzemyslaw Czarnowski }
777e13c2760SPrzemyslaw Czarnowski 
77822db1728SEd Tanous inline void requestNBDVirtualMediaRoutes(App& app)
779107077deSPrzemyslaw Czarnowski {
780*0fda0f12SGeorge Liu     BMCWEB_ROUTE(
781*0fda0f12SGeorge Liu         app,
782*0fda0f12SGeorge Liu         "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
783ed398213SEd Tanous         .privileges(redfish::privileges::postVirtualMedia)
78422db1728SEd Tanous         .methods(boost::beast::http::verb::post)(
78522db1728SEd Tanous             [](const crow::Request& req,
78622db1728SEd Tanous                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
78722db1728SEd Tanous                const std::string& name, const std::string& resName) {
78822db1728SEd Tanous                 if (name != "bmc")
789107077deSPrzemyslaw Czarnowski                 {
79022db1728SEd Tanous                     messages::resourceNotFound(asyncResp->res,
79122db1728SEd Tanous                                                "VirtualMedia.Insert", resName);
792107077deSPrzemyslaw Czarnowski 
793107077deSPrzemyslaw Czarnowski                     return;
794107077deSPrzemyslaw Czarnowski                 }
795107077deSPrzemyslaw Czarnowski 
79622db1728SEd Tanous                 crow::connections::systemBus->async_method_call(
79722db1728SEd Tanous                     [asyncResp, req,
79822db1728SEd Tanous                      resName](const boost::system::error_code ec,
79922db1728SEd Tanous                               const GetObjectType& getObjectType) {
80022db1728SEd Tanous                         if (ec)
80122db1728SEd Tanous                         {
80222db1728SEd Tanous                             BMCWEB_LOG_ERROR
80322db1728SEd Tanous                                 << "ObjectMapper::GetObject call failed: "
80422db1728SEd Tanous                                 << ec;
80522db1728SEd Tanous                             messages::internalError(asyncResp->res);
806107077deSPrzemyslaw Czarnowski 
80722db1728SEd Tanous                             return;
80822db1728SEd Tanous                         }
80922db1728SEd Tanous                         std::string service = getObjectType.begin()->first;
81022db1728SEd Tanous                         BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
81122db1728SEd Tanous 
81222db1728SEd Tanous                         crow::connections::systemBus->async_method_call(
81322db1728SEd Tanous                             [service, resName, req,
81422db1728SEd Tanous                              asyncResp](const boost::system::error_code ec,
81522db1728SEd Tanous                                         ManagedObjectType& subtree) {
81622db1728SEd Tanous                                 if (ec)
81722db1728SEd Tanous                                 {
81822db1728SEd Tanous                                     BMCWEB_LOG_DEBUG << "DBUS response error";
81922db1728SEd Tanous 
82022db1728SEd Tanous                                     return;
82122db1728SEd Tanous                                 }
82222db1728SEd Tanous 
82322db1728SEd Tanous                                 for (const auto& object : subtree)
82422db1728SEd Tanous                                 {
82522db1728SEd Tanous                                     const std::string& path =
82622db1728SEd Tanous                                         static_cast<const std::string&>(
82722db1728SEd Tanous                                             object.first);
82822db1728SEd Tanous 
82922db1728SEd Tanous                                     std::size_t lastIndex = path.rfind('/');
83022db1728SEd Tanous                                     if (lastIndex == std::string::npos)
83122db1728SEd Tanous                                     {
83222db1728SEd Tanous                                         continue;
83322db1728SEd Tanous                                     }
83422db1728SEd Tanous 
83522db1728SEd Tanous                                     lastIndex += 1;
83622db1728SEd Tanous 
83722db1728SEd Tanous                                     if (path.substr(lastIndex) == resName)
83822db1728SEd Tanous                                     {
83922db1728SEd Tanous                                         lastIndex = path.rfind("Proxy");
84022db1728SEd Tanous                                         if (lastIndex != std::string::npos)
84122db1728SEd Tanous                                         {
84222db1728SEd Tanous                                             // Not possible in proxy mode
84322db1728SEd Tanous                                             BMCWEB_LOG_DEBUG
84422db1728SEd Tanous                                                 << "InsertMedia not "
84522db1728SEd Tanous                                                    "allowed in proxy mode";
84622db1728SEd Tanous                                             messages::resourceNotFound(
84722db1728SEd Tanous                                                 asyncResp->res,
84822db1728SEd Tanous                                                 "VirtualMedia.InsertMedia",
84922db1728SEd Tanous                                                 resName);
85022db1728SEd Tanous 
85122db1728SEd Tanous                                             return;
85222db1728SEd Tanous                                         }
85322db1728SEd Tanous 
85422db1728SEd Tanous                                         lastIndex = path.rfind("Legacy");
85522db1728SEd Tanous                                         if (lastIndex == std::string::npos)
85622db1728SEd Tanous                                         {
85722db1728SEd Tanous                                             continue;
85822db1728SEd Tanous                                         }
85922db1728SEd Tanous 
86022db1728SEd Tanous                                         // Legacy mode
86122db1728SEd Tanous                                         std::string imageUrl;
86222db1728SEd Tanous                                         std::optional<std::string> userName;
86322db1728SEd Tanous                                         std::optional<std::string> password;
86422db1728SEd Tanous                                         std::optional<std::string>
86522db1728SEd Tanous                                             transferMethod;
86622db1728SEd Tanous                                         std::optional<std::string>
86722db1728SEd Tanous                                             transferProtocolType;
86822db1728SEd Tanous                                         std::optional<bool> writeProtected =
86922db1728SEd Tanous                                             true;
87022db1728SEd Tanous                                         std::optional<bool> inserted;
87122db1728SEd Tanous 
87222db1728SEd Tanous                                         // Read obligatory parameters (url of
87322db1728SEd Tanous                                         // image)
87422db1728SEd Tanous                                         if (!json_util::readJson(
87522db1728SEd Tanous                                                 req, asyncResp->res, "Image",
87622db1728SEd Tanous                                                 imageUrl, "WriteProtected",
87722db1728SEd Tanous                                                 writeProtected, "UserName",
87822db1728SEd Tanous                                                 userName, "Password", password,
87922db1728SEd Tanous                                                 "Inserted", inserted,
88022db1728SEd Tanous                                                 "TransferMethod",
88122db1728SEd Tanous                                                 transferMethod,
88222db1728SEd Tanous                                                 "TransferProtocolType",
88322db1728SEd Tanous                                                 transferProtocolType))
88422db1728SEd Tanous                                         {
88522db1728SEd Tanous                                             BMCWEB_LOG_DEBUG
88622db1728SEd Tanous                                                 << "Image is not provided";
88722db1728SEd Tanous                                             return;
88822db1728SEd Tanous                                         }
88922db1728SEd Tanous 
89022db1728SEd Tanous                                         bool paramsValid = validateParams(
89122db1728SEd Tanous                                             asyncResp->res, imageUrl, inserted,
89222db1728SEd Tanous                                             transferMethod,
89322db1728SEd Tanous                                             transferProtocolType);
89422db1728SEd Tanous 
89522db1728SEd Tanous                                         if (paramsValid == false)
89622db1728SEd Tanous                                         {
89722db1728SEd Tanous                                             return;
89822db1728SEd Tanous                                         }
89922db1728SEd Tanous 
90022db1728SEd Tanous                                         // manager is irrelevant for
90122db1728SEd Tanous                                         // VirtualMedia dbus calls
90222db1728SEd Tanous                                         doMountVmLegacy(asyncResp, service,
90322db1728SEd Tanous                                                         resName, imageUrl,
90422db1728SEd Tanous                                                         !(*writeProtected),
90522db1728SEd Tanous                                                         std::move(*userName),
90622db1728SEd Tanous                                                         std::move(*password));
90722db1728SEd Tanous 
90822db1728SEd Tanous                                         return;
90922db1728SEd Tanous                                     }
91022db1728SEd Tanous                                 }
91122db1728SEd Tanous                                 BMCWEB_LOG_DEBUG << "Parent item not found";
91222db1728SEd Tanous                                 messages::resourceNotFound(
91322db1728SEd Tanous                                     asyncResp->res, "VirtualMedia", resName);
91422db1728SEd Tanous                             },
91522db1728SEd Tanous                             service, "/xyz/openbmc_project/VirtualMedia",
91622db1728SEd Tanous                             "org.freedesktop.DBus.ObjectManager",
91722db1728SEd Tanous                             "GetManagedObjects");
91822db1728SEd Tanous                     },
91922db1728SEd Tanous                     "xyz.openbmc_project.ObjectMapper",
92022db1728SEd Tanous                     "/xyz/openbmc_project/object_mapper",
92122db1728SEd Tanous                     "xyz.openbmc_project.ObjectMapper", "GetObject",
92222db1728SEd Tanous                     "/xyz/openbmc_project/VirtualMedia",
92322db1728SEd Tanous                     std::array<const char*, 0>());
92422db1728SEd Tanous             });
92522db1728SEd Tanous 
926*0fda0f12SGeorge Liu     BMCWEB_ROUTE(
927*0fda0f12SGeorge Liu         app,
928*0fda0f12SGeorge Liu         "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
929ed398213SEd Tanous         .privileges(redfish::privileges::postVirtualMedia)
93022db1728SEd Tanous         .methods(boost::beast::http::verb::post)(
93122db1728SEd Tanous             [](const crow::Request& req,
93222db1728SEd Tanous                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
93322db1728SEd Tanous                const std::string& name, const std::string& resName) {
934107077deSPrzemyslaw Czarnowski                 if (name != "bmc")
935107077deSPrzemyslaw Czarnowski                 {
93622db1728SEd Tanous                     messages::resourceNotFound(asyncResp->res,
93722db1728SEd Tanous                                                "VirtualMedia.Eject", resName);
93822db1728SEd Tanous 
93922db1728SEd Tanous                     return;
94022db1728SEd Tanous                 }
94122db1728SEd Tanous 
94222db1728SEd Tanous                 crow::connections::systemBus->async_method_call(
94322db1728SEd Tanous                     [asyncResp, req,
94422db1728SEd Tanous                      resName](const boost::system::error_code ec,
94522db1728SEd Tanous                               const GetObjectType& getObjectType) {
94622db1728SEd Tanous                         if (ec)
94722db1728SEd Tanous                         {
94822db1728SEd Tanous                             BMCWEB_LOG_ERROR
94922db1728SEd Tanous                                 << "ObjectMapper::GetObject call failed: "
95022db1728SEd Tanous                                 << ec;
95122db1728SEd Tanous                             messages::internalError(asyncResp->res);
95222db1728SEd Tanous 
95322db1728SEd Tanous                             return;
95422db1728SEd Tanous                         }
95522db1728SEd Tanous                         std::string service = getObjectType.begin()->first;
95622db1728SEd Tanous                         BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
95722db1728SEd Tanous 
95822db1728SEd Tanous                         crow::connections::systemBus->async_method_call(
95922db1728SEd Tanous                             [resName, service, req, asyncResp{asyncResp}](
96022db1728SEd Tanous                                 const boost::system::error_code ec,
96122db1728SEd Tanous                                 ManagedObjectType& subtree) {
96222db1728SEd Tanous                                 if (ec)
96322db1728SEd Tanous                                 {
96422db1728SEd Tanous                                     BMCWEB_LOG_DEBUG << "DBUS response error";
96522db1728SEd Tanous 
96622db1728SEd Tanous                                     return;
96722db1728SEd Tanous                                 }
96822db1728SEd Tanous 
96922db1728SEd Tanous                                 for (const auto& object : subtree)
97022db1728SEd Tanous                                 {
97122db1728SEd Tanous                                     const std::string& path =
97222db1728SEd Tanous                                         static_cast<const std::string&>(
97322db1728SEd Tanous                                             object.first);
97422db1728SEd Tanous 
97522db1728SEd Tanous                                     std::size_t lastIndex = path.rfind('/');
97622db1728SEd Tanous                                     if (lastIndex == std::string::npos)
97722db1728SEd Tanous                                     {
97822db1728SEd Tanous                                         continue;
97922db1728SEd Tanous                                     }
98022db1728SEd Tanous 
98122db1728SEd Tanous                                     lastIndex += 1;
98222db1728SEd Tanous 
98322db1728SEd Tanous                                     if (path.substr(lastIndex) == resName)
98422db1728SEd Tanous                                     {
98522db1728SEd Tanous                                         lastIndex = path.rfind("Proxy");
98622db1728SEd Tanous                                         if (lastIndex != std::string::npos)
98722db1728SEd Tanous                                         {
98822db1728SEd Tanous                                             // Proxy mode
98922db1728SEd Tanous                                             doVmAction(asyncResp, service,
99022db1728SEd Tanous                                                        resName, false);
99122db1728SEd Tanous                                         }
99222db1728SEd Tanous 
99322db1728SEd Tanous                                         lastIndex = path.rfind("Legacy");
99422db1728SEd Tanous                                         if (lastIndex != std::string::npos)
99522db1728SEd Tanous                                         {
99622db1728SEd Tanous                                             // Legacy mode
99722db1728SEd Tanous                                             doVmAction(asyncResp, service,
99822db1728SEd Tanous                                                        resName, true);
99922db1728SEd Tanous                                         }
100022db1728SEd Tanous 
100122db1728SEd Tanous                                         return;
100222db1728SEd Tanous                                     }
100322db1728SEd Tanous                                 }
100422db1728SEd Tanous                                 BMCWEB_LOG_DEBUG << "Parent item not found";
100522db1728SEd Tanous                                 messages::resourceNotFound(
100622db1728SEd Tanous                                     asyncResp->res, "VirtualMedia", resName);
100722db1728SEd Tanous                             },
100822db1728SEd Tanous                             service, "/xyz/openbmc_project/VirtualMedia",
100922db1728SEd Tanous                             "org.freedesktop.DBus.ObjectManager",
101022db1728SEd Tanous                             "GetManagedObjects");
101122db1728SEd Tanous                     },
101222db1728SEd Tanous                     "xyz.openbmc_project.ObjectMapper",
101322db1728SEd Tanous                     "/xyz/openbmc_project/object_mapper",
101422db1728SEd Tanous                     "xyz.openbmc_project.ObjectMapper", "GetObject",
101522db1728SEd Tanous                     "/xyz/openbmc_project/VirtualMedia",
101622db1728SEd Tanous                     std::array<const char*, 0>());
101722db1728SEd Tanous             });
101822db1728SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
1019ed398213SEd Tanous         .privileges(redfish::privileges::getVirtualMediaCollection)
102022db1728SEd Tanous         .methods(boost::beast::http::verb::get)(
102122db1728SEd Tanous             [](const crow::Request& /* req */,
102222db1728SEd Tanous                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
102322db1728SEd Tanous                const std::string& name) {
102422db1728SEd Tanous                 if (name != "bmc")
102522db1728SEd Tanous                 {
102622db1728SEd Tanous                     messages::resourceNotFound(asyncResp->res, "VirtualMedia",
102722db1728SEd Tanous                                                name);
1028107077deSPrzemyslaw Czarnowski 
1029107077deSPrzemyslaw Czarnowski                     return;
1030107077deSPrzemyslaw Czarnowski                 }
1031107077deSPrzemyslaw Czarnowski 
10328d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.type"] =
1033107077deSPrzemyslaw Czarnowski                     "#VirtualMediaCollection.VirtualMediaCollection";
10348d1b46d7Szhanghch05                 asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
10358d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.id"] =
1036d6c414f3SPrzemyslaw Czarnowski                     "/redfish/v1/Managers/" + name + "/VirtualMedia";
1037107077deSPrzemyslaw Czarnowski 
1038107077deSPrzemyslaw Czarnowski                 crow::connections::systemBus->async_method_call(
1039107077deSPrzemyslaw Czarnowski                     [asyncResp, name](const boost::system::error_code ec,
1040107077deSPrzemyslaw Czarnowski                                       const GetObjectType& getObjectType) {
1041107077deSPrzemyslaw Czarnowski                         if (ec)
1042107077deSPrzemyslaw Czarnowski                         {
104322db1728SEd Tanous                             BMCWEB_LOG_ERROR
104422db1728SEd Tanous                                 << "ObjectMapper::GetObject call failed: "
1045107077deSPrzemyslaw Czarnowski                                 << ec;
1046107077deSPrzemyslaw Czarnowski                             messages::internalError(asyncResp->res);
1047107077deSPrzemyslaw Czarnowski 
1048107077deSPrzemyslaw Czarnowski                             return;
1049107077deSPrzemyslaw Czarnowski                         }
1050107077deSPrzemyslaw Czarnowski                         std::string service = getObjectType.begin()->first;
1051107077deSPrzemyslaw Czarnowski                         BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1052107077deSPrzemyslaw Czarnowski 
1053107077deSPrzemyslaw Czarnowski                         getVmResourceList(asyncResp, service, name);
1054107077deSPrzemyslaw Czarnowski                     },
1055107077deSPrzemyslaw Czarnowski                     "xyz.openbmc_project.ObjectMapper",
1056107077deSPrzemyslaw Czarnowski                     "/xyz/openbmc_project/object_mapper",
1057107077deSPrzemyslaw Czarnowski                     "xyz.openbmc_project.ObjectMapper", "GetObject",
105822db1728SEd Tanous                     "/xyz/openbmc_project/VirtualMedia",
105922db1728SEd Tanous                     std::array<const char*, 0>());
106022db1728SEd Tanous             });
1061107077deSPrzemyslaw Czarnowski 
106222db1728SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
1063ed398213SEd Tanous         .privileges(redfish::privileges::getVirtualMedia)
106422db1728SEd Tanous         .methods(boost::beast::http::verb::get)(
106522db1728SEd Tanous             [](const crow::Request& /* req */,
106622db1728SEd Tanous                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
106722db1728SEd Tanous                const std::string& name, const std::string& resName) {
1068107077deSPrzemyslaw Czarnowski                 if (name != "bmc")
1069107077deSPrzemyslaw Czarnowski                 {
107022db1728SEd Tanous                     messages::resourceNotFound(asyncResp->res, "VirtualMedia",
107122db1728SEd Tanous                                                resName);
1072107077deSPrzemyslaw Czarnowski 
1073107077deSPrzemyslaw Czarnowski                     return;
1074107077deSPrzemyslaw Czarnowski                 }
1075107077deSPrzemyslaw Czarnowski 
1076107077deSPrzemyslaw Czarnowski                 crow::connections::systemBus->async_method_call(
107722db1728SEd Tanous                     [asyncResp, name,
107822db1728SEd Tanous                      resName](const boost::system::error_code ec,
1079107077deSPrzemyslaw Czarnowski                               const GetObjectType& getObjectType) {
1080107077deSPrzemyslaw Czarnowski                         if (ec)
1081107077deSPrzemyslaw Czarnowski                         {
108222db1728SEd Tanous                             BMCWEB_LOG_ERROR
108322db1728SEd Tanous                                 << "ObjectMapper::GetObject call failed: "
1084107077deSPrzemyslaw Czarnowski                                 << ec;
1085107077deSPrzemyslaw Czarnowski                             messages::internalError(asyncResp->res);
1086107077deSPrzemyslaw Czarnowski 
1087107077deSPrzemyslaw Czarnowski                             return;
1088107077deSPrzemyslaw Czarnowski                         }
1089107077deSPrzemyslaw Czarnowski                         std::string service = getObjectType.begin()->first;
1090107077deSPrzemyslaw Czarnowski                         BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1091107077deSPrzemyslaw Czarnowski 
1092107077deSPrzemyslaw Czarnowski                         getVmData(asyncResp, service, name, resName);
1093107077deSPrzemyslaw Czarnowski                     },
1094107077deSPrzemyslaw Czarnowski                     "xyz.openbmc_project.ObjectMapper",
1095107077deSPrzemyslaw Czarnowski                     "/xyz/openbmc_project/object_mapper",
1096107077deSPrzemyslaw Czarnowski                     "xyz.openbmc_project.ObjectMapper", "GetObject",
109722db1728SEd Tanous                     "/xyz/openbmc_project/VirtualMedia",
109822db1728SEd Tanous                     std::array<const char*, 0>());
109922db1728SEd Tanous             });
1100107077deSPrzemyslaw Czarnowski }
1101107077deSPrzemyslaw Czarnowski 
1102107077deSPrzemyslaw Czarnowski } // namespace redfish
1103