xref: /openbmc/bmcweb/features/redfish/lib/virtual_media.hpp (revision 22db1728d5fdcac0a257976afa99034ae189c753)
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
24e13c2760SPrzemyslaw Czarnowski #include <account_service.hpp>
259e319cf0SAnna Platash #include <boost/url/url_view.hpp>
26107077deSPrzemyslaw Czarnowski 
27107077deSPrzemyslaw Czarnowski namespace redfish
28107077deSPrzemyslaw Czarnowski {
299e319cf0SAnna Platash /**
309e319cf0SAnna Platash  * @brief Function extracts transfer protocol name from URI.
319e319cf0SAnna Platash  */
32*22db1728SEd Tanous inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
339e319cf0SAnna Platash {
349e319cf0SAnna Platash     try
359e319cf0SAnna Platash     {
369e319cf0SAnna Platash         std::string_view scheme = boost::urls::url_view(imageUri).scheme();
379e319cf0SAnna Platash         if (scheme == "smb")
389e319cf0SAnna Platash         {
399e319cf0SAnna Platash             return "CIFS";
409e319cf0SAnna Platash         }
41*22db1728SEd Tanous         if (scheme == "https")
429e319cf0SAnna Platash         {
439e319cf0SAnna Platash             return "HTTPS";
449e319cf0SAnna Platash         }
459e319cf0SAnna Platash     }
469e319cf0SAnna Platash     catch (std::exception& p)
479e319cf0SAnna Platash     {
489e319cf0SAnna Platash         BMCWEB_LOG_ERROR << p.what();
499e319cf0SAnna Platash     }
509e319cf0SAnna Platash     return "None";
519e319cf0SAnna Platash }
52107077deSPrzemyslaw Czarnowski 
53107077deSPrzemyslaw Czarnowski /**
54107077deSPrzemyslaw Czarnowski  * @brief Read all known properties from VM object interfaces
55107077deSPrzemyslaw Czarnowski  */
56*22db1728SEd Tanous inline void
578d1b46d7Szhanghch05     vmParseInterfaceObject(const DbusInterfaceType& interface,
588d1b46d7Szhanghch05                            const std::shared_ptr<bmcweb::AsyncResp>& aResp)
59107077deSPrzemyslaw Czarnowski {
60107077deSPrzemyslaw Czarnowski     const auto mountPointIface =
61107077deSPrzemyslaw Czarnowski         interface.find("xyz.openbmc_project.VirtualMedia.MountPoint");
62107077deSPrzemyslaw Czarnowski     if (mountPointIface == interface.cend())
63107077deSPrzemyslaw Czarnowski     {
64107077deSPrzemyslaw Czarnowski         BMCWEB_LOG_DEBUG << "Interface MountPoint not found";
65107077deSPrzemyslaw Czarnowski         return;
66107077deSPrzemyslaw Czarnowski     }
67107077deSPrzemyslaw Czarnowski 
68107077deSPrzemyslaw Czarnowski     const auto processIface =
69107077deSPrzemyslaw Czarnowski         interface.find("xyz.openbmc_project.VirtualMedia.Process");
70107077deSPrzemyslaw Czarnowski     if (processIface == interface.cend())
71107077deSPrzemyslaw Czarnowski     {
72107077deSPrzemyslaw Czarnowski         BMCWEB_LOG_DEBUG << "Interface Process not found";
73107077deSPrzemyslaw Czarnowski         return;
74107077deSPrzemyslaw Czarnowski     }
75107077deSPrzemyslaw Czarnowski 
76107077deSPrzemyslaw Czarnowski     const auto endpointIdProperty = mountPointIface->second.find("EndpointId");
77107077deSPrzemyslaw Czarnowski     if (endpointIdProperty == mountPointIface->second.cend())
78107077deSPrzemyslaw Czarnowski     {
79107077deSPrzemyslaw Czarnowski         BMCWEB_LOG_DEBUG << "Property EndpointId not found";
80107077deSPrzemyslaw Czarnowski         return;
81107077deSPrzemyslaw Czarnowski     }
82107077deSPrzemyslaw Czarnowski 
83107077deSPrzemyslaw Czarnowski     const auto activeProperty = processIface->second.find("Active");
84107077deSPrzemyslaw Czarnowski     if (activeProperty == processIface->second.cend())
85107077deSPrzemyslaw Czarnowski     {
86107077deSPrzemyslaw Czarnowski         BMCWEB_LOG_DEBUG << "Property Active not found";
87107077deSPrzemyslaw Czarnowski         return;
88107077deSPrzemyslaw Czarnowski     }
89107077deSPrzemyslaw Czarnowski 
90107077deSPrzemyslaw Czarnowski     const bool* activeValue = std::get_if<bool>(&activeProperty->second);
91107077deSPrzemyslaw Czarnowski     if (!activeValue)
92107077deSPrzemyslaw Czarnowski     {
93107077deSPrzemyslaw Czarnowski         BMCWEB_LOG_DEBUG << "Value Active not found";
94107077deSPrzemyslaw Czarnowski         return;
95107077deSPrzemyslaw Czarnowski     }
96107077deSPrzemyslaw Czarnowski 
97107077deSPrzemyslaw Czarnowski     const std::string* endpointIdValue =
98107077deSPrzemyslaw Czarnowski         std::get_if<std::string>(&endpointIdProperty->second);
99107077deSPrzemyslaw Czarnowski     if (endpointIdValue)
100107077deSPrzemyslaw Czarnowski     {
101107077deSPrzemyslaw Czarnowski         if (!endpointIdValue->empty())
102107077deSPrzemyslaw Czarnowski         {
103107077deSPrzemyslaw Czarnowski             // Proxy mode
104d04ba325SPrzemyslaw Czarnowski             aResp->res.jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
105d04ba325SPrzemyslaw Czarnowski                 *endpointIdValue;
106107077deSPrzemyslaw Czarnowski             aResp->res.jsonValue["TransferProtocolType"] = "OEM";
107107077deSPrzemyslaw Czarnowski             aResp->res.jsonValue["Inserted"] = *activeValue;
108107077deSPrzemyslaw Czarnowski             if (*activeValue == true)
109107077deSPrzemyslaw Czarnowski             {
110107077deSPrzemyslaw Czarnowski                 aResp->res.jsonValue["ConnectedVia"] = "Applet";
111107077deSPrzemyslaw Czarnowski             }
112107077deSPrzemyslaw Czarnowski         }
113107077deSPrzemyslaw Czarnowski         else
114107077deSPrzemyslaw Czarnowski         {
115107077deSPrzemyslaw Czarnowski             // Legacy mode
1169e319cf0SAnna Platash             for (const auto& property : mountPointIface->second)
1179e319cf0SAnna Platash             {
1189e319cf0SAnna Platash                 if (property.first == "ImageURL")
119107077deSPrzemyslaw Czarnowski                 {
120107077deSPrzemyslaw Czarnowski                     const std::string* imageUrlValue =
1219e319cf0SAnna Platash                         std::get_if<std::string>(&property.second);
122107077deSPrzemyslaw Czarnowski                     if (imageUrlValue && !imageUrlValue->empty())
123107077deSPrzemyslaw Czarnowski                     {
124da4784d8SPrzemyslaw Czarnowski                         std::filesystem::path filePath = *imageUrlValue;
125da4784d8SPrzemyslaw Czarnowski                         if (!filePath.has_filename())
126da4784d8SPrzemyslaw Czarnowski                         {
1279e319cf0SAnna Platash                             // this will handle https share, which not
1289e319cf0SAnna Platash                             // necessarily has to have filename given.
129da4784d8SPrzemyslaw Czarnowski                             aResp->res.jsonValue["ImageName"] = "";
130da4784d8SPrzemyslaw Czarnowski                         }
131da4784d8SPrzemyslaw Czarnowski                         else
132da4784d8SPrzemyslaw Czarnowski                         {
1339e319cf0SAnna Platash                             aResp->res.jsonValue["ImageName"] =
1349e319cf0SAnna Platash                                 filePath.filename();
135da4784d8SPrzemyslaw Czarnowski                         }
136da4784d8SPrzemyslaw Czarnowski 
137da4784d8SPrzemyslaw Czarnowski                         aResp->res.jsonValue["Image"] = *imageUrlValue;
138107077deSPrzemyslaw Czarnowski                         aResp->res.jsonValue["Inserted"] = *activeValue;
1399e319cf0SAnna Platash                         aResp->res.jsonValue["TransferProtocolType"] =
1409e319cf0SAnna Platash                             getTransferProtocolTypeFromUri(*imageUrlValue);
1419e319cf0SAnna Platash 
142107077deSPrzemyslaw Czarnowski                         if (*activeValue == true)
143107077deSPrzemyslaw Czarnowski                         {
144107077deSPrzemyslaw Czarnowski                             aResp->res.jsonValue["ConnectedVia"] = "URI";
145107077deSPrzemyslaw Czarnowski                         }
146107077deSPrzemyslaw Czarnowski                     }
147107077deSPrzemyslaw Czarnowski                 }
1489e319cf0SAnna Platash                 else if (property.first == "WriteProtected")
1499e319cf0SAnna Platash                 {
1509e319cf0SAnna Platash                     const bool* writeProtectedValue =
1519e319cf0SAnna Platash                         std::get_if<bool>(&property.second);
1529e319cf0SAnna Platash                     if (writeProtectedValue)
1539e319cf0SAnna Platash                     {
1549e319cf0SAnna Platash                         aResp->res.jsonValue["WriteProtected"] =
1559e319cf0SAnna Platash                             *writeProtectedValue;
1569e319cf0SAnna Platash                     }
1579e319cf0SAnna Platash                 }
1589e319cf0SAnna Platash             }
159107077deSPrzemyslaw Czarnowski         }
160107077deSPrzemyslaw Czarnowski     }
161107077deSPrzemyslaw Czarnowski }
162107077deSPrzemyslaw Czarnowski 
163107077deSPrzemyslaw Czarnowski /**
164107077deSPrzemyslaw Czarnowski  * @brief Fill template for Virtual Media Item.
165107077deSPrzemyslaw Czarnowski  */
166*22db1728SEd Tanous inline nlohmann::json vmItemTemplate(const std::string& name,
167107077deSPrzemyslaw Czarnowski                                      const std::string& resName)
168107077deSPrzemyslaw Czarnowski {
169107077deSPrzemyslaw Czarnowski     nlohmann::json item;
170*22db1728SEd Tanous 
171*22db1728SEd Tanous     std::string id = "/redfish/v1/Managers/";
172*22db1728SEd Tanous     id += name;
173*22db1728SEd Tanous     id += "/VirtualMedia/";
174*22db1728SEd Tanous     id += resName;
175*22db1728SEd Tanous     item["@odata.id"] = std::move(id);
176*22db1728SEd Tanous 
177d04ba325SPrzemyslaw Czarnowski     item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
178107077deSPrzemyslaw Czarnowski     item["Name"] = "Virtual Removable Media";
179107077deSPrzemyslaw Czarnowski     item["Id"] = resName;
180107077deSPrzemyslaw Czarnowski     item["WriteProtected"] = true;
181107077deSPrzemyslaw Czarnowski     item["MediaTypes"] = {"CD", "USBStick"};
182107077deSPrzemyslaw Czarnowski     item["TransferMethod"] = "Stream";
183d04ba325SPrzemyslaw Czarnowski     item["Oem"]["OpenBMC"]["@odata.type"] =
184d04ba325SPrzemyslaw Czarnowski         "#OemVirtualMedia.v1_0_0.VirtualMedia";
185107077deSPrzemyslaw Czarnowski 
186107077deSPrzemyslaw Czarnowski     return item;
187107077deSPrzemyslaw Czarnowski }
188107077deSPrzemyslaw Czarnowski 
189107077deSPrzemyslaw Czarnowski /**
190107077deSPrzemyslaw Czarnowski  *  @brief Fills collection data
191107077deSPrzemyslaw Czarnowski  */
192*22db1728SEd Tanous inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
193107077deSPrzemyslaw Czarnowski                               const std::string& service,
194107077deSPrzemyslaw Czarnowski                               const std::string& name)
195107077deSPrzemyslaw Czarnowski {
196107077deSPrzemyslaw Czarnowski     BMCWEB_LOG_DEBUG << "Get available Virtual Media resources.";
197107077deSPrzemyslaw Czarnowski     crow::connections::systemBus->async_method_call(
198107077deSPrzemyslaw Czarnowski         [name, aResp{std::move(aResp)}](const boost::system::error_code ec,
199107077deSPrzemyslaw Czarnowski                                         ManagedObjectType& subtree) {
200107077deSPrzemyslaw Czarnowski             if (ec)
201107077deSPrzemyslaw Czarnowski             {
202107077deSPrzemyslaw Czarnowski                 BMCWEB_LOG_DEBUG << "DBUS response error";
203107077deSPrzemyslaw Czarnowski                 return;
204107077deSPrzemyslaw Czarnowski             }
205107077deSPrzemyslaw Czarnowski             nlohmann::json& members = aResp->res.jsonValue["Members"];
206107077deSPrzemyslaw Czarnowski             members = nlohmann::json::array();
207107077deSPrzemyslaw Czarnowski 
208107077deSPrzemyslaw Czarnowski             for (const auto& object : subtree)
209107077deSPrzemyslaw Czarnowski             {
210107077deSPrzemyslaw Czarnowski                 nlohmann::json item;
2112dfd18efSEd Tanous                 std::string path = object.first.filename();
2122dfd18efSEd Tanous                 if (path.empty())
213107077deSPrzemyslaw Czarnowski                 {
214107077deSPrzemyslaw Czarnowski                     continue;
215107077deSPrzemyslaw Czarnowski                 }
216107077deSPrzemyslaw Czarnowski 
217*22db1728SEd Tanous                 std::string id = "/redfish/v1/Managers/";
218*22db1728SEd Tanous                 id += name;
219*22db1728SEd Tanous                 id += "/VirtualMedia/";
220*22db1728SEd Tanous                 id += path;
221107077deSPrzemyslaw Czarnowski 
222*22db1728SEd Tanous                 item["@odata.id"] = std::move(id);
223107077deSPrzemyslaw Czarnowski                 members.emplace_back(std::move(item));
224107077deSPrzemyslaw Czarnowski             }
225107077deSPrzemyslaw Czarnowski             aResp->res.jsonValue["Members@odata.count"] = members.size();
226107077deSPrzemyslaw Czarnowski         },
227107077deSPrzemyslaw Czarnowski         service, "/xyz/openbmc_project/VirtualMedia",
228107077deSPrzemyslaw Czarnowski         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
229107077deSPrzemyslaw Czarnowski }
230107077deSPrzemyslaw Czarnowski 
231107077deSPrzemyslaw Czarnowski /**
232107077deSPrzemyslaw Czarnowski  *  @brief Fills data for specific resource
233107077deSPrzemyslaw Czarnowski  */
234*22db1728SEd Tanous inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
235107077deSPrzemyslaw Czarnowski                       const std::string& service, const std::string& name,
236107077deSPrzemyslaw Czarnowski                       const std::string& resName)
237107077deSPrzemyslaw Czarnowski {
238107077deSPrzemyslaw Czarnowski     BMCWEB_LOG_DEBUG << "Get Virtual Media resource data.";
239107077deSPrzemyslaw Czarnowski 
240107077deSPrzemyslaw Czarnowski     crow::connections::systemBus->async_method_call(
241107077deSPrzemyslaw Czarnowski         [resName, name, aResp](const boost::system::error_code ec,
242107077deSPrzemyslaw Czarnowski                                ManagedObjectType& subtree) {
243107077deSPrzemyslaw Czarnowski             if (ec)
244107077deSPrzemyslaw Czarnowski             {
245107077deSPrzemyslaw Czarnowski                 BMCWEB_LOG_DEBUG << "DBUS response error";
246e13c2760SPrzemyslaw Czarnowski 
247107077deSPrzemyslaw Czarnowski                 return;
248107077deSPrzemyslaw Czarnowski             }
249107077deSPrzemyslaw Czarnowski 
250107077deSPrzemyslaw Czarnowski             for (auto& item : subtree)
251107077deSPrzemyslaw Czarnowski             {
2522dfd18efSEd Tanous                 std::string thispath = item.first.filename();
2532dfd18efSEd Tanous                 if (thispath.empty())
254107077deSPrzemyslaw Czarnowski                 {
255107077deSPrzemyslaw Czarnowski                     continue;
256107077deSPrzemyslaw Czarnowski                 }
257107077deSPrzemyslaw Czarnowski 
2582dfd18efSEd Tanous                 if (thispath != resName)
259107077deSPrzemyslaw Czarnowski                 {
260107077deSPrzemyslaw Czarnowski                     continue;
261107077deSPrzemyslaw Czarnowski                 }
262107077deSPrzemyslaw Czarnowski 
2631a6258dcSPrzemyslaw Czarnowski                 // "Legacy"/"Proxy"
2641a6258dcSPrzemyslaw Czarnowski                 auto mode = item.first.parent_path();
2651a6258dcSPrzemyslaw Czarnowski                 // "VirtualMedia"
2661a6258dcSPrzemyslaw Czarnowski                 auto type = mode.parent_path();
2671a6258dcSPrzemyslaw Czarnowski                 if (mode.filename().empty() || type.filename().empty())
2681a6258dcSPrzemyslaw Czarnowski                 {
2691a6258dcSPrzemyslaw Czarnowski                     continue;
2701a6258dcSPrzemyslaw Czarnowski                 }
2711a6258dcSPrzemyslaw Czarnowski 
2721a6258dcSPrzemyslaw Czarnowski                 if (type.filename() != "VirtualMedia")
2731a6258dcSPrzemyslaw Czarnowski                 {
2741a6258dcSPrzemyslaw Czarnowski                     continue;
2751a6258dcSPrzemyslaw Czarnowski                 }
2761a6258dcSPrzemyslaw Czarnowski 
277107077deSPrzemyslaw Czarnowski                 aResp->res.jsonValue = vmItemTemplate(name, resName);
278*22db1728SEd Tanous                 std::string actionsId = "/redfish/v1/Managers/";
279*22db1728SEd Tanous                 actionsId += name;
280*22db1728SEd Tanous                 actionsId += "/VirtualMedia/";
281*22db1728SEd Tanous                 actionsId += resName;
282*22db1728SEd Tanous                 actionsId += "/Actions";
283107077deSPrzemyslaw Czarnowski 
284e13c2760SPrzemyslaw Czarnowski                 // Check if dbus path is Legacy type
2851a6258dcSPrzemyslaw Czarnowski                 if (mode.filename() == "Legacy")
286e13c2760SPrzemyslaw Czarnowski                 {
287e13c2760SPrzemyslaw Czarnowski                     aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
288e13c2760SPrzemyslaw Czarnowski                                         ["target"] =
289*22db1728SEd Tanous                         actionsId + "/VirtualMedia.InsertMedia";
290e13c2760SPrzemyslaw Czarnowski                 }
291e13c2760SPrzemyslaw Czarnowski 
292107077deSPrzemyslaw Czarnowski                 vmParseInterfaceObject(item.second, aResp);
293107077deSPrzemyslaw Czarnowski 
294e13c2760SPrzemyslaw Czarnowski                 aResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"]
295e13c2760SPrzemyslaw Czarnowski                                     ["target"] =
296*22db1728SEd Tanous                     actionsId + "/VirtualMedia.EjectMedia";
297e13c2760SPrzemyslaw Czarnowski 
298107077deSPrzemyslaw Czarnowski                 return;
299107077deSPrzemyslaw Czarnowski             }
300107077deSPrzemyslaw Czarnowski 
301107077deSPrzemyslaw Czarnowski             messages::resourceNotFound(
302d04ba325SPrzemyslaw Czarnowski                 aResp->res, "#VirtualMedia.v1_3_0.VirtualMedia", resName);
303107077deSPrzemyslaw Czarnowski         },
304107077deSPrzemyslaw Czarnowski         service, "/xyz/openbmc_project/VirtualMedia",
305107077deSPrzemyslaw Czarnowski         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
306107077deSPrzemyslaw Czarnowski }
307107077deSPrzemyslaw Czarnowski 
308e13c2760SPrzemyslaw Czarnowski /**
309c6f4e017SAgata Olender  * @brief Transfer protocols supported for InsertMedia action.
310c6f4e017SAgata Olender  *
311c6f4e017SAgata Olender  */
312c6f4e017SAgata Olender enum class TransferProtocol
313c6f4e017SAgata Olender {
314c6f4e017SAgata Olender     https,
315c6f4e017SAgata Olender     smb,
316c6f4e017SAgata Olender     invalid
317c6f4e017SAgata Olender };
318c6f4e017SAgata Olender 
319c6f4e017SAgata Olender /**
320c6f4e017SAgata Olender  * @brief Function extracts transfer protocol type from URI.
321c6f4e017SAgata Olender  *
322c6f4e017SAgata Olender  */
323*22db1728SEd Tanous inline std::optional<TransferProtocol>
324c6f4e017SAgata Olender     getTransferProtocolFromUri(const std::string& imageUri)
325c6f4e017SAgata Olender {
3269e319cf0SAnna Platash     try
3279e319cf0SAnna Platash     {
3289e319cf0SAnna Platash         std::string_view scheme = boost::urls::url_view(imageUri).scheme();
3299e319cf0SAnna Platash         if (scheme == "smb")
330c6f4e017SAgata Olender         {
331c6f4e017SAgata Olender             return TransferProtocol::smb;
332c6f4e017SAgata Olender         }
33381ce609eSEd Tanous         if (scheme == "https")
334c6f4e017SAgata Olender         {
335c6f4e017SAgata Olender             return TransferProtocol::https;
336c6f4e017SAgata Olender         }
337*22db1728SEd Tanous         if (!scheme.empty())
338c6f4e017SAgata Olender         {
339c6f4e017SAgata Olender             return TransferProtocol::invalid;
340c6f4e017SAgata Olender         }
341c6f4e017SAgata Olender     }
3429e319cf0SAnna Platash     catch (std::exception& p)
3439e319cf0SAnna Platash     {
3449e319cf0SAnna Platash         BMCWEB_LOG_ERROR << p.what();
3459e319cf0SAnna Platash     }
3469e319cf0SAnna Platash 
3479e319cf0SAnna Platash     return {};
348c6f4e017SAgata Olender }
349c6f4e017SAgata Olender 
350c6f4e017SAgata Olender /**
351c6f4e017SAgata Olender  * @brief Function convert transfer protocol from string param.
352c6f4e017SAgata Olender  *
353c6f4e017SAgata Olender  */
354*22db1728SEd Tanous inline std::optional<TransferProtocol> getTransferProtocolFromParam(
355c6f4e017SAgata Olender     const std::optional<std::string>& transferProtocolType)
356c6f4e017SAgata Olender {
357c6f4e017SAgata Olender     if (transferProtocolType == std::nullopt)
358c6f4e017SAgata Olender     {
359c6f4e017SAgata Olender         return {};
360c6f4e017SAgata Olender     }
361c6f4e017SAgata Olender 
362c6f4e017SAgata Olender     if (*transferProtocolType == "CIFS")
363c6f4e017SAgata Olender     {
364c6f4e017SAgata Olender         return TransferProtocol::smb;
365c6f4e017SAgata Olender     }
366c6f4e017SAgata Olender 
367c6f4e017SAgata Olender     if (*transferProtocolType == "HTTPS")
368c6f4e017SAgata Olender     {
369c6f4e017SAgata Olender         return TransferProtocol::https;
370c6f4e017SAgata Olender     }
371c6f4e017SAgata Olender 
372c6f4e017SAgata Olender     return TransferProtocol::invalid;
373c6f4e017SAgata Olender }
374c6f4e017SAgata Olender 
375c6f4e017SAgata Olender /**
376c6f4e017SAgata Olender  * @brief Function extends URI with transfer protocol type.
377c6f4e017SAgata Olender  *
378c6f4e017SAgata Olender  */
379*22db1728SEd Tanous inline std::string
380c6f4e017SAgata Olender     getUriWithTransferProtocol(const std::string& imageUri,
381c6f4e017SAgata Olender                                const TransferProtocol& transferProtocol)
382c6f4e017SAgata Olender {
383c6f4e017SAgata Olender     if (transferProtocol == TransferProtocol::smb)
384c6f4e017SAgata Olender     {
385c6f4e017SAgata Olender         return "smb://" + imageUri;
386c6f4e017SAgata Olender     }
387c6f4e017SAgata Olender 
388c6f4e017SAgata Olender     if (transferProtocol == TransferProtocol::https)
389c6f4e017SAgata Olender     {
390c6f4e017SAgata Olender         return "https://" + imageUri;
391c6f4e017SAgata Olender     }
392c6f4e017SAgata Olender 
393c6f4e017SAgata Olender     return imageUri;
394c6f4e017SAgata Olender }
395c6f4e017SAgata Olender 
396c6f4e017SAgata Olender /**
397c6f4e017SAgata Olender  * @brief Function validate parameters of insert media request.
398c6f4e017SAgata Olender  *
399c6f4e017SAgata Olender  */
400*22db1728SEd Tanous inline bool
401*22db1728SEd Tanous     validateParams(crow::Response& res, std::string& imageUrl,
402c6f4e017SAgata Olender                    const std::optional<bool>& inserted,
403c6f4e017SAgata Olender                    const std::optional<std::string>& transferMethod,
404c6f4e017SAgata Olender                    const std::optional<std::string>& transferProtocolType)
405c6f4e017SAgata Olender {
406c6f4e017SAgata Olender     BMCWEB_LOG_DEBUG << "Validation started";
407c6f4e017SAgata Olender     // required param imageUrl must not be empty
408c6f4e017SAgata Olender     if (imageUrl.empty())
409c6f4e017SAgata Olender     {
410c6f4e017SAgata Olender         BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
411c6f4e017SAgata Olender 
412*22db1728SEd Tanous         messages::propertyValueFormatError(res, "<empty>", "Image");
413c6f4e017SAgata Olender 
414c6f4e017SAgata Olender         return false;
415c6f4e017SAgata Olender     }
416c6f4e017SAgata Olender 
417c6f4e017SAgata Olender     // optional param inserted must be true
418c6f4e017SAgata Olender     if ((inserted != std::nullopt) && (*inserted != true))
419c6f4e017SAgata Olender     {
420c6f4e017SAgata Olender         BMCWEB_LOG_ERROR
421c6f4e017SAgata Olender             << "Request action optional parameter Inserted must be true.";
422c6f4e017SAgata Olender 
423*22db1728SEd Tanous         messages::actionParameterNotSupported(res, "Inserted", "InsertMedia");
424c6f4e017SAgata Olender 
425c6f4e017SAgata Olender         return false;
426c6f4e017SAgata Olender     }
427c6f4e017SAgata Olender 
428c6f4e017SAgata Olender     // optional param transferMethod must be stream
429c6f4e017SAgata Olender     if ((transferMethod != std::nullopt) && (*transferMethod != "Stream"))
430c6f4e017SAgata Olender     {
431c6f4e017SAgata Olender         BMCWEB_LOG_ERROR << "Request action optional parameter "
432c6f4e017SAgata Olender                             "TransferMethod must be Stream.";
433c6f4e017SAgata Olender 
434*22db1728SEd Tanous         messages::actionParameterNotSupported(res, "TransferMethod",
435*22db1728SEd Tanous                                               "InsertMedia");
436c6f4e017SAgata Olender 
437c6f4e017SAgata Olender         return false;
438c6f4e017SAgata Olender     }
439c6f4e017SAgata Olender 
440c6f4e017SAgata Olender     std::optional<TransferProtocol> uriTransferProtocolType =
441c6f4e017SAgata Olender         getTransferProtocolFromUri(imageUrl);
442c6f4e017SAgata Olender 
443c6f4e017SAgata Olender     std::optional<TransferProtocol> paramTransferProtocolType =
444c6f4e017SAgata Olender         getTransferProtocolFromParam(transferProtocolType);
445c6f4e017SAgata Olender 
446c6f4e017SAgata Olender     // ImageUrl does not contain valid protocol type
447c6f4e017SAgata Olender     if (*uriTransferProtocolType == TransferProtocol::invalid)
448c6f4e017SAgata Olender     {
449c6f4e017SAgata Olender         BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
450c6f4e017SAgata Olender                             "contain specified protocol type from list: "
451c6f4e017SAgata Olender                             "(smb, https).";
452c6f4e017SAgata Olender 
453*22db1728SEd Tanous         messages::resourceAtUriInUnknownFormat(res, imageUrl);
454c6f4e017SAgata Olender 
455c6f4e017SAgata Olender         return false;
456c6f4e017SAgata Olender     }
457c6f4e017SAgata Olender 
458c6f4e017SAgata Olender     // transferProtocolType should contain value from list
459c6f4e017SAgata Olender     if (*paramTransferProtocolType == TransferProtocol::invalid)
460c6f4e017SAgata Olender     {
461c6f4e017SAgata Olender         BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
462c6f4e017SAgata Olender                             "must be provided with value from list: "
463c6f4e017SAgata Olender                             "(CIFS, HTTPS).";
464c6f4e017SAgata Olender 
465*22db1728SEd Tanous         messages::propertyValueNotInList(res, *transferProtocolType,
466*22db1728SEd Tanous                                          "TransferProtocolType");
467c6f4e017SAgata Olender         return false;
468c6f4e017SAgata Olender     }
469c6f4e017SAgata Olender 
470c6f4e017SAgata Olender     // valid transfer protocol not provided either with URI nor param
471c6f4e017SAgata Olender     if ((uriTransferProtocolType == std::nullopt) &&
472c6f4e017SAgata Olender         (paramTransferProtocolType == std::nullopt))
473c6f4e017SAgata Olender     {
474c6f4e017SAgata Olender         BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
475c6f4e017SAgata Olender                             "contain specified protocol type or param "
476c6f4e017SAgata Olender                             "TransferProtocolType must be provided.";
477c6f4e017SAgata Olender 
478*22db1728SEd Tanous         messages::resourceAtUriInUnknownFormat(res, imageUrl);
479c6f4e017SAgata Olender 
480c6f4e017SAgata Olender         return false;
481c6f4e017SAgata Olender     }
482c6f4e017SAgata Olender 
483c6f4e017SAgata Olender     // valid transfer protocol provided both with URI and param
484c6f4e017SAgata Olender     if ((paramTransferProtocolType != std::nullopt) &&
485c6f4e017SAgata Olender         (uriTransferProtocolType != std::nullopt))
486c6f4e017SAgata Olender     {
487c6f4e017SAgata Olender         // check if protocol is the same for URI and param
488c6f4e017SAgata Olender         if (*paramTransferProtocolType != *uriTransferProtocolType)
489c6f4e017SAgata Olender         {
490c6f4e017SAgata Olender             BMCWEB_LOG_ERROR << "Request action parameter "
491c6f4e017SAgata Olender                                 "TransferProtocolType must  contain the "
492c6f4e017SAgata Olender                                 "same protocol type as protocol type "
493c6f4e017SAgata Olender                                 "provided with param imageUrl.";
494c6f4e017SAgata Olender 
495*22db1728SEd Tanous             messages::actionParameterValueTypeError(res, *transferProtocolType,
496*22db1728SEd Tanous                                                     "TransferProtocolType",
497*22db1728SEd Tanous                                                     "InsertMedia");
498c6f4e017SAgata Olender 
499c6f4e017SAgata Olender             return false;
500c6f4e017SAgata Olender         }
501c6f4e017SAgata Olender     }
502c6f4e017SAgata Olender 
503c6f4e017SAgata Olender     // validation passed
504c6f4e017SAgata Olender     // add protocol to URI if needed
505c6f4e017SAgata Olender     if (uriTransferProtocolType == std::nullopt)
506c6f4e017SAgata Olender     {
507*22db1728SEd Tanous         imageUrl =
508*22db1728SEd Tanous             getUriWithTransferProtocol(imageUrl, *paramTransferProtocolType);
509c6f4e017SAgata Olender     }
510c6f4e017SAgata Olender 
511c6f4e017SAgata Olender     return true;
512c6f4e017SAgata Olender }
513c6f4e017SAgata Olender 
5141214b7e7SGunnar Mills template <typename T>
5151214b7e7SGunnar Mills static void secureCleanup(T& value)
516988fb7b2SAdrian Ambrożewicz {
517988fb7b2SAdrian Ambrożewicz     auto raw = const_cast<typename T::value_type*>(value.data());
518988fb7b2SAdrian Ambrożewicz     explicit_bzero(raw, value.size() * sizeof(*raw));
519988fb7b2SAdrian Ambrożewicz }
520988fb7b2SAdrian Ambrożewicz 
521988fb7b2SAdrian Ambrożewicz class Credentials
522988fb7b2SAdrian Ambrożewicz {
523988fb7b2SAdrian Ambrożewicz   public:
524988fb7b2SAdrian Ambrożewicz     Credentials(std::string&& user, std::string&& password) :
525988fb7b2SAdrian Ambrożewicz         userBuf(std::move(user)), passBuf(std::move(password))
5261214b7e7SGunnar Mills     {}
527988fb7b2SAdrian Ambrożewicz 
528988fb7b2SAdrian Ambrożewicz     ~Credentials()
529988fb7b2SAdrian Ambrożewicz     {
530988fb7b2SAdrian Ambrożewicz         secureCleanup(userBuf);
531988fb7b2SAdrian Ambrożewicz         secureCleanup(passBuf);
532988fb7b2SAdrian Ambrożewicz     }
533988fb7b2SAdrian Ambrożewicz 
534988fb7b2SAdrian Ambrożewicz     const std::string& user()
535988fb7b2SAdrian Ambrożewicz     {
536988fb7b2SAdrian Ambrożewicz         return userBuf;
537988fb7b2SAdrian Ambrożewicz     }
538988fb7b2SAdrian Ambrożewicz 
539988fb7b2SAdrian Ambrożewicz     const std::string& password()
540988fb7b2SAdrian Ambrożewicz     {
541988fb7b2SAdrian Ambrożewicz         return passBuf;
542988fb7b2SAdrian Ambrożewicz     }
543988fb7b2SAdrian Ambrożewicz 
544988fb7b2SAdrian Ambrożewicz     Credentials() = delete;
545988fb7b2SAdrian Ambrożewicz     Credentials(const Credentials&) = delete;
546988fb7b2SAdrian Ambrożewicz     Credentials& operator=(const Credentials&) = delete;
547988fb7b2SAdrian Ambrożewicz 
548*22db1728SEd Tanous   private:
549988fb7b2SAdrian Ambrożewicz     std::string userBuf;
550988fb7b2SAdrian Ambrożewicz     std::string passBuf;
551988fb7b2SAdrian Ambrożewicz };
552988fb7b2SAdrian Ambrożewicz 
553988fb7b2SAdrian Ambrożewicz class CredentialsProvider
554988fb7b2SAdrian Ambrożewicz {
555988fb7b2SAdrian Ambrożewicz   public:
5561214b7e7SGunnar Mills     template <typename T>
5571214b7e7SGunnar Mills     struct Deleter
558988fb7b2SAdrian Ambrożewicz     {
559988fb7b2SAdrian Ambrożewicz         void operator()(T* buff) const
560988fb7b2SAdrian Ambrożewicz         {
561988fb7b2SAdrian Ambrożewicz             if (buff)
562988fb7b2SAdrian Ambrożewicz             {
563988fb7b2SAdrian Ambrożewicz                 secureCleanup(*buff);
564988fb7b2SAdrian Ambrożewicz                 delete buff;
565988fb7b2SAdrian Ambrożewicz             }
566988fb7b2SAdrian Ambrożewicz         }
567988fb7b2SAdrian Ambrożewicz     };
568988fb7b2SAdrian Ambrożewicz 
569988fb7b2SAdrian Ambrożewicz     using Buffer = std::vector<char>;
570988fb7b2SAdrian Ambrożewicz     using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
571988fb7b2SAdrian Ambrożewicz     // Using explicit definition instead of std::function to avoid implicit
572988fb7b2SAdrian Ambrożewicz     // conversions eg. stack copy instead of reference
573988fb7b2SAdrian Ambrożewicz     using FormatterFunc = void(const std::string& username,
574988fb7b2SAdrian Ambrożewicz                                const std::string& password, Buffer& dest);
575988fb7b2SAdrian Ambrożewicz 
576988fb7b2SAdrian Ambrożewicz     CredentialsProvider(std::string&& user, std::string&& password) :
577988fb7b2SAdrian Ambrożewicz         credentials(std::move(user), std::move(password))
5781214b7e7SGunnar Mills     {}
579988fb7b2SAdrian Ambrożewicz 
580988fb7b2SAdrian Ambrożewicz     const std::string& user()
581988fb7b2SAdrian Ambrożewicz     {
582988fb7b2SAdrian Ambrożewicz         return credentials.user();
583988fb7b2SAdrian Ambrożewicz     }
584988fb7b2SAdrian Ambrożewicz 
585988fb7b2SAdrian Ambrożewicz     const std::string& password()
586988fb7b2SAdrian Ambrożewicz     {
587988fb7b2SAdrian Ambrożewicz         return credentials.password();
588988fb7b2SAdrian Ambrożewicz     }
589988fb7b2SAdrian Ambrożewicz 
59081ce609eSEd Tanous     SecureBuffer pack(FormatterFunc formatter)
591988fb7b2SAdrian Ambrożewicz     {
592988fb7b2SAdrian Ambrożewicz         SecureBuffer packed{new Buffer{}};
593988fb7b2SAdrian Ambrożewicz         if (formatter)
594988fb7b2SAdrian Ambrożewicz         {
595988fb7b2SAdrian Ambrożewicz             formatter(credentials.user(), credentials.password(), *packed);
596988fb7b2SAdrian Ambrożewicz         }
597988fb7b2SAdrian Ambrożewicz 
598988fb7b2SAdrian Ambrożewicz         return packed;
599988fb7b2SAdrian Ambrożewicz     }
600988fb7b2SAdrian Ambrożewicz 
601988fb7b2SAdrian Ambrożewicz   private:
602988fb7b2SAdrian Ambrożewicz     Credentials credentials;
603988fb7b2SAdrian Ambrożewicz };
604988fb7b2SAdrian Ambrożewicz 
605988fb7b2SAdrian Ambrożewicz // Wrapper for boost::async_pipe ensuring proper pipe cleanup
6061214b7e7SGunnar Mills template <typename Buffer>
6071214b7e7SGunnar Mills class Pipe
608988fb7b2SAdrian Ambrożewicz {
609988fb7b2SAdrian Ambrożewicz   public:
610988fb7b2SAdrian Ambrożewicz     using unix_fd = sdbusplus::message::unix_fd;
611988fb7b2SAdrian Ambrożewicz 
612988fb7b2SAdrian Ambrożewicz     Pipe(boost::asio::io_context& io, Buffer&& buffer) :
613988fb7b2SAdrian Ambrożewicz         impl(io), buffer{std::move(buffer)}
6141214b7e7SGunnar Mills     {}
615988fb7b2SAdrian Ambrożewicz 
616988fb7b2SAdrian Ambrożewicz     ~Pipe()
617988fb7b2SAdrian Ambrożewicz     {
618988fb7b2SAdrian Ambrożewicz         // Named pipe needs to be explicitly removed
619988fb7b2SAdrian Ambrożewicz         impl.close();
620988fb7b2SAdrian Ambrożewicz     }
621988fb7b2SAdrian Ambrożewicz 
622988fb7b2SAdrian Ambrożewicz     unix_fd fd()
623988fb7b2SAdrian Ambrożewicz     {
624988fb7b2SAdrian Ambrożewicz         return unix_fd{impl.native_source()};
625988fb7b2SAdrian Ambrożewicz     }
626988fb7b2SAdrian Ambrożewicz 
627988fb7b2SAdrian Ambrożewicz     template <typename WriteHandler>
62881ce609eSEd Tanous     void asyncWrite(WriteHandler&& handler)
629988fb7b2SAdrian Ambrożewicz     {
630988fb7b2SAdrian Ambrożewicz         impl.async_write_some(data(), std::forward<WriteHandler>(handler));
631988fb7b2SAdrian Ambrożewicz     }
632988fb7b2SAdrian Ambrożewicz 
633988fb7b2SAdrian Ambrożewicz   private:
634988fb7b2SAdrian Ambrożewicz     // Specialization for pointer types
635988fb7b2SAdrian Ambrożewicz     template <typename B = Buffer>
636988fb7b2SAdrian Ambrożewicz     typename std::enable_if<boost::has_dereference<B>::value,
637988fb7b2SAdrian Ambrożewicz                             boost::asio::const_buffer>::type
638988fb7b2SAdrian Ambrożewicz         data()
639988fb7b2SAdrian Ambrożewicz     {
640988fb7b2SAdrian Ambrożewicz         return boost::asio::buffer(*buffer);
641988fb7b2SAdrian Ambrożewicz     }
642988fb7b2SAdrian Ambrożewicz 
643988fb7b2SAdrian Ambrożewicz     template <typename B = Buffer>
644988fb7b2SAdrian Ambrożewicz     typename std::enable_if<!boost::has_dereference<B>::value,
645988fb7b2SAdrian Ambrożewicz                             boost::asio::const_buffer>::type
646988fb7b2SAdrian Ambrożewicz         data()
647988fb7b2SAdrian Ambrożewicz     {
648988fb7b2SAdrian Ambrożewicz         return boost::asio::buffer(buffer);
649988fb7b2SAdrian Ambrożewicz     }
650988fb7b2SAdrian Ambrożewicz 
651988fb7b2SAdrian Ambrożewicz     const std::string name;
652988fb7b2SAdrian Ambrożewicz     boost::process::async_pipe impl;
653988fb7b2SAdrian Ambrożewicz     Buffer buffer;
654988fb7b2SAdrian Ambrożewicz };
655988fb7b2SAdrian Ambrożewicz 
656e13c2760SPrzemyslaw Czarnowski /**
657e13c2760SPrzemyslaw Czarnowski  * @brief Function transceives data with dbus directly.
658e13c2760SPrzemyslaw Czarnowski  *
659e13c2760SPrzemyslaw Czarnowski  * All BMC state properties will be retrieved before sending reset request.
660e13c2760SPrzemyslaw Czarnowski  */
661*22db1728SEd Tanous inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
662e13c2760SPrzemyslaw Czarnowski                             const std::string& service, const std::string& name,
663988fb7b2SAdrian Ambrożewicz                             const std::string& imageUrl, const bool rw,
664988fb7b2SAdrian Ambrożewicz                             std::string&& userName, std::string&& password)
665e13c2760SPrzemyslaw Czarnowski {
666988fb7b2SAdrian Ambrożewicz     using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
667988fb7b2SAdrian Ambrożewicz     constexpr const size_t secretLimit = 1024;
668988fb7b2SAdrian Ambrożewicz 
669988fb7b2SAdrian Ambrożewicz     std::shared_ptr<SecurePipe> secretPipe;
670988fb7b2SAdrian Ambrożewicz     std::variant<int, SecurePipe::unix_fd> unixFd = -1;
671988fb7b2SAdrian Ambrożewicz 
672988fb7b2SAdrian Ambrożewicz     if (!userName.empty() || !password.empty())
673988fb7b2SAdrian Ambrożewicz     {
674988fb7b2SAdrian Ambrożewicz         // Encapsulate in safe buffer
675988fb7b2SAdrian Ambrożewicz         CredentialsProvider credentials(std::move(userName),
676988fb7b2SAdrian Ambrożewicz                                         std::move(password));
677988fb7b2SAdrian Ambrożewicz 
678988fb7b2SAdrian Ambrożewicz         // Payload must contain data + NULL delimiters
679988fb7b2SAdrian Ambrożewicz         if (credentials.user().size() + credentials.password().size() + 2 >
680988fb7b2SAdrian Ambrożewicz             secretLimit)
681988fb7b2SAdrian Ambrożewicz         {
682988fb7b2SAdrian Ambrożewicz             BMCWEB_LOG_ERROR << "Credentials too long to handle";
683988fb7b2SAdrian Ambrożewicz             messages::unrecognizedRequestBody(asyncResp->res);
684988fb7b2SAdrian Ambrożewicz             return;
685988fb7b2SAdrian Ambrożewicz         }
686988fb7b2SAdrian Ambrożewicz 
687988fb7b2SAdrian Ambrożewicz         // Pack secret
688*22db1728SEd Tanous         auto secret = credentials.pack(
689*22db1728SEd Tanous             [](const auto& user, const auto& pass, auto& buff) {
690988fb7b2SAdrian Ambrożewicz                 std::copy(user.begin(), user.end(), std::back_inserter(buff));
691988fb7b2SAdrian Ambrożewicz                 buff.push_back('\0');
692988fb7b2SAdrian Ambrożewicz                 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
693988fb7b2SAdrian Ambrożewicz                 buff.push_back('\0');
694988fb7b2SAdrian Ambrożewicz             });
695988fb7b2SAdrian Ambrożewicz 
696988fb7b2SAdrian Ambrożewicz         // Open pipe
697988fb7b2SAdrian Ambrożewicz         secretPipe = std::make_shared<SecurePipe>(
698*22db1728SEd Tanous             crow::connections::systemBus->get_io_context(), std::move(secret));
699988fb7b2SAdrian Ambrożewicz         unixFd = secretPipe->fd();
700988fb7b2SAdrian Ambrożewicz 
701988fb7b2SAdrian Ambrożewicz         // Pass secret over pipe
70281ce609eSEd Tanous         secretPipe->asyncWrite(
703f5b16f03SVikram Bodireddy             [asyncResp](const boost::system::error_code& ec, std::size_t) {
704988fb7b2SAdrian Ambrożewicz                 if (ec)
705988fb7b2SAdrian Ambrożewicz                 {
706988fb7b2SAdrian Ambrożewicz                     BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
707988fb7b2SAdrian Ambrożewicz                     messages::internalError(asyncResp->res);
708988fb7b2SAdrian Ambrożewicz                 }
709988fb7b2SAdrian Ambrożewicz             });
710988fb7b2SAdrian Ambrożewicz     }
711988fb7b2SAdrian Ambrożewicz 
712e13c2760SPrzemyslaw Czarnowski     crow::connections::systemBus->async_method_call(
713988fb7b2SAdrian Ambrożewicz         [asyncResp, secretPipe](const boost::system::error_code ec,
714988fb7b2SAdrian Ambrożewicz                                 bool success) {
715e13c2760SPrzemyslaw Czarnowski             if (ec)
716e13c2760SPrzemyslaw Czarnowski             {
717e13c2760SPrzemyslaw Czarnowski                 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
718e13c2760SPrzemyslaw Czarnowski                 messages::internalError(asyncResp->res);
719d6da5bebSAdrian Ambrożewicz             }
720d6da5bebSAdrian Ambrożewicz             else if (!success)
721d6da5bebSAdrian Ambrożewicz             {
722d6da5bebSAdrian Ambrożewicz                 BMCWEB_LOG_ERROR << "Service responded with error";
723d6da5bebSAdrian Ambrożewicz                 messages::generalError(asyncResp->res);
724e13c2760SPrzemyslaw Czarnowski             }
725e13c2760SPrzemyslaw Czarnowski         },
726e13c2760SPrzemyslaw Czarnowski         service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
727988fb7b2SAdrian Ambrożewicz         "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
728988fb7b2SAdrian Ambrożewicz         unixFd);
729e13c2760SPrzemyslaw Czarnowski }
730e13c2760SPrzemyslaw Czarnowski 
731e13c2760SPrzemyslaw Czarnowski /**
732e13c2760SPrzemyslaw Czarnowski  * @brief Function transceives data with dbus directly.
733e13c2760SPrzemyslaw Czarnowski  *
734e13c2760SPrzemyslaw Czarnowski  * All BMC state properties will be retrieved before sending reset request.
735e13c2760SPrzemyslaw Czarnowski  */
736*22db1728SEd Tanous inline void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
737e13c2760SPrzemyslaw Czarnowski                        const std::string& service, const std::string& name,
738e13c2760SPrzemyslaw Czarnowski                        bool legacy)
739e13c2760SPrzemyslaw Czarnowski {
740e13c2760SPrzemyslaw Czarnowski 
741e13c2760SPrzemyslaw Czarnowski     // Legacy mount requires parameter with image
742e13c2760SPrzemyslaw Czarnowski     if (legacy)
743e13c2760SPrzemyslaw Czarnowski     {
744e13c2760SPrzemyslaw Czarnowski         crow::connections::systemBus->async_method_call(
745e13c2760SPrzemyslaw Czarnowski             [asyncResp](const boost::system::error_code ec) {
746e13c2760SPrzemyslaw Czarnowski                 if (ec)
747e13c2760SPrzemyslaw Czarnowski                 {
748e13c2760SPrzemyslaw Czarnowski                     BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
749e13c2760SPrzemyslaw Czarnowski 
750e13c2760SPrzemyslaw Czarnowski                     messages::internalError(asyncResp->res);
751e13c2760SPrzemyslaw Czarnowski                     return;
752e13c2760SPrzemyslaw Czarnowski                 }
753e13c2760SPrzemyslaw Czarnowski             },
754e13c2760SPrzemyslaw Czarnowski             service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
755e13c2760SPrzemyslaw Czarnowski             "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
756e13c2760SPrzemyslaw Czarnowski     }
757e13c2760SPrzemyslaw Czarnowski     else // proxy
758e13c2760SPrzemyslaw Czarnowski     {
759e13c2760SPrzemyslaw Czarnowski         crow::connections::systemBus->async_method_call(
760e13c2760SPrzemyslaw Czarnowski             [asyncResp](const boost::system::error_code ec) {
761e13c2760SPrzemyslaw Czarnowski                 if (ec)
762e13c2760SPrzemyslaw Czarnowski                 {
763e13c2760SPrzemyslaw Czarnowski                     BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
764e13c2760SPrzemyslaw Czarnowski 
765e13c2760SPrzemyslaw Czarnowski                     messages::internalError(asyncResp->res);
766e13c2760SPrzemyslaw Czarnowski                     return;
767e13c2760SPrzemyslaw Czarnowski                 }
768e13c2760SPrzemyslaw Czarnowski             },
769e13c2760SPrzemyslaw Czarnowski             service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
770e13c2760SPrzemyslaw Czarnowski             "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
771e13c2760SPrzemyslaw Czarnowski     }
772e13c2760SPrzemyslaw Czarnowski }
773e13c2760SPrzemyslaw Czarnowski 
774*22db1728SEd Tanous inline void requestNBDVirtualMediaRoutes(App& app)
775107077deSPrzemyslaw Czarnowski {
776*22db1728SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/"
777*22db1728SEd Tanous                       "VirtualMedia.InsertMedia")
778*22db1728SEd Tanous         .privileges({"ConfigureManager"})
779*22db1728SEd Tanous         .methods(boost::beast::http::verb::post)(
780*22db1728SEd Tanous             [](const crow::Request& req,
781*22db1728SEd Tanous                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
782*22db1728SEd Tanous                const std::string& name, const std::string& resName) {
783*22db1728SEd Tanous                 if (name != "bmc")
784107077deSPrzemyslaw Czarnowski                 {
785*22db1728SEd Tanous                     messages::resourceNotFound(asyncResp->res,
786*22db1728SEd Tanous                                                "VirtualMedia.Insert", resName);
787107077deSPrzemyslaw Czarnowski 
788107077deSPrzemyslaw Czarnowski                     return;
789107077deSPrzemyslaw Czarnowski                 }
790107077deSPrzemyslaw Czarnowski 
791*22db1728SEd Tanous                 crow::connections::systemBus->async_method_call(
792*22db1728SEd Tanous                     [asyncResp, req,
793*22db1728SEd Tanous                      resName](const boost::system::error_code ec,
794*22db1728SEd Tanous                               const GetObjectType& getObjectType) {
795*22db1728SEd Tanous                         if (ec)
796*22db1728SEd Tanous                         {
797*22db1728SEd Tanous                             BMCWEB_LOG_ERROR
798*22db1728SEd Tanous                                 << "ObjectMapper::GetObject call failed: "
799*22db1728SEd Tanous                                 << ec;
800*22db1728SEd Tanous                             messages::internalError(asyncResp->res);
801107077deSPrzemyslaw Czarnowski 
802*22db1728SEd Tanous                             return;
803*22db1728SEd Tanous                         }
804*22db1728SEd Tanous                         std::string service = getObjectType.begin()->first;
805*22db1728SEd Tanous                         BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
806*22db1728SEd Tanous 
807*22db1728SEd Tanous                         crow::connections::systemBus->async_method_call(
808*22db1728SEd Tanous                             [service, resName, req,
809*22db1728SEd Tanous                              asyncResp](const boost::system::error_code ec,
810*22db1728SEd Tanous                                         ManagedObjectType& subtree) {
811*22db1728SEd Tanous                                 if (ec)
812*22db1728SEd Tanous                                 {
813*22db1728SEd Tanous                                     BMCWEB_LOG_DEBUG << "DBUS response error";
814*22db1728SEd Tanous 
815*22db1728SEd Tanous                                     return;
816*22db1728SEd Tanous                                 }
817*22db1728SEd Tanous 
818*22db1728SEd Tanous                                 for (const auto& object : subtree)
819*22db1728SEd Tanous                                 {
820*22db1728SEd Tanous                                     const std::string& path =
821*22db1728SEd Tanous                                         static_cast<const std::string&>(
822*22db1728SEd Tanous                                             object.first);
823*22db1728SEd Tanous 
824*22db1728SEd Tanous                                     std::size_t lastIndex = path.rfind('/');
825*22db1728SEd Tanous                                     if (lastIndex == std::string::npos)
826*22db1728SEd Tanous                                     {
827*22db1728SEd Tanous                                         continue;
828*22db1728SEd Tanous                                     }
829*22db1728SEd Tanous 
830*22db1728SEd Tanous                                     lastIndex += 1;
831*22db1728SEd Tanous 
832*22db1728SEd Tanous                                     if (path.substr(lastIndex) == resName)
833*22db1728SEd Tanous                                     {
834*22db1728SEd Tanous                                         lastIndex = path.rfind("Proxy");
835*22db1728SEd Tanous                                         if (lastIndex != std::string::npos)
836*22db1728SEd Tanous                                         {
837*22db1728SEd Tanous                                             // Not possible in proxy mode
838*22db1728SEd Tanous                                             BMCWEB_LOG_DEBUG
839*22db1728SEd Tanous                                                 << "InsertMedia not "
840*22db1728SEd Tanous                                                    "allowed in proxy mode";
841*22db1728SEd Tanous                                             messages::resourceNotFound(
842*22db1728SEd Tanous                                                 asyncResp->res,
843*22db1728SEd Tanous                                                 "VirtualMedia.InsertMedia",
844*22db1728SEd Tanous                                                 resName);
845*22db1728SEd Tanous 
846*22db1728SEd Tanous                                             return;
847*22db1728SEd Tanous                                         }
848*22db1728SEd Tanous 
849*22db1728SEd Tanous                                         lastIndex = path.rfind("Legacy");
850*22db1728SEd Tanous                                         if (lastIndex == std::string::npos)
851*22db1728SEd Tanous                                         {
852*22db1728SEd Tanous                                             continue;
853*22db1728SEd Tanous                                         }
854*22db1728SEd Tanous 
855*22db1728SEd Tanous                                         // Legacy mode
856*22db1728SEd Tanous                                         std::string imageUrl;
857*22db1728SEd Tanous                                         std::optional<std::string> userName;
858*22db1728SEd Tanous                                         std::optional<std::string> password;
859*22db1728SEd Tanous                                         std::optional<std::string>
860*22db1728SEd Tanous                                             transferMethod;
861*22db1728SEd Tanous                                         std::optional<std::string>
862*22db1728SEd Tanous                                             transferProtocolType;
863*22db1728SEd Tanous                                         std::optional<bool> writeProtected =
864*22db1728SEd Tanous                                             true;
865*22db1728SEd Tanous                                         std::optional<bool> inserted;
866*22db1728SEd Tanous 
867*22db1728SEd Tanous                                         // Read obligatory parameters (url of
868*22db1728SEd Tanous                                         // image)
869*22db1728SEd Tanous                                         if (!json_util::readJson(
870*22db1728SEd Tanous                                                 req, asyncResp->res, "Image",
871*22db1728SEd Tanous                                                 imageUrl, "WriteProtected",
872*22db1728SEd Tanous                                                 writeProtected, "UserName",
873*22db1728SEd Tanous                                                 userName, "Password", password,
874*22db1728SEd Tanous                                                 "Inserted", inserted,
875*22db1728SEd Tanous                                                 "TransferMethod",
876*22db1728SEd Tanous                                                 transferMethod,
877*22db1728SEd Tanous                                                 "TransferProtocolType",
878*22db1728SEd Tanous                                                 transferProtocolType))
879*22db1728SEd Tanous                                         {
880*22db1728SEd Tanous                                             BMCWEB_LOG_DEBUG
881*22db1728SEd Tanous                                                 << "Image is not provided";
882*22db1728SEd Tanous                                             return;
883*22db1728SEd Tanous                                         }
884*22db1728SEd Tanous 
885*22db1728SEd Tanous                                         bool paramsValid = validateParams(
886*22db1728SEd Tanous                                             asyncResp->res, imageUrl, inserted,
887*22db1728SEd Tanous                                             transferMethod,
888*22db1728SEd Tanous                                             transferProtocolType);
889*22db1728SEd Tanous 
890*22db1728SEd Tanous                                         if (paramsValid == false)
891*22db1728SEd Tanous                                         {
892*22db1728SEd Tanous                                             return;
893*22db1728SEd Tanous                                         }
894*22db1728SEd Tanous 
895*22db1728SEd Tanous                                         // manager is irrelevant for
896*22db1728SEd Tanous                                         // VirtualMedia dbus calls
897*22db1728SEd Tanous                                         doMountVmLegacy(asyncResp, service,
898*22db1728SEd Tanous                                                         resName, imageUrl,
899*22db1728SEd Tanous                                                         !(*writeProtected),
900*22db1728SEd Tanous                                                         std::move(*userName),
901*22db1728SEd Tanous                                                         std::move(*password));
902*22db1728SEd Tanous 
903*22db1728SEd Tanous                                         return;
904*22db1728SEd Tanous                                     }
905*22db1728SEd Tanous                                 }
906*22db1728SEd Tanous                                 BMCWEB_LOG_DEBUG << "Parent item not found";
907*22db1728SEd Tanous                                 messages::resourceNotFound(
908*22db1728SEd Tanous                                     asyncResp->res, "VirtualMedia", resName);
909*22db1728SEd Tanous                             },
910*22db1728SEd Tanous                             service, "/xyz/openbmc_project/VirtualMedia",
911*22db1728SEd Tanous                             "org.freedesktop.DBus.ObjectManager",
912*22db1728SEd Tanous                             "GetManagedObjects");
913*22db1728SEd Tanous                     },
914*22db1728SEd Tanous                     "xyz.openbmc_project.ObjectMapper",
915*22db1728SEd Tanous                     "/xyz/openbmc_project/object_mapper",
916*22db1728SEd Tanous                     "xyz.openbmc_project.ObjectMapper", "GetObject",
917*22db1728SEd Tanous                     "/xyz/openbmc_project/VirtualMedia",
918*22db1728SEd Tanous                     std::array<const char*, 0>());
919*22db1728SEd Tanous             });
920*22db1728SEd Tanous 
921*22db1728SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/"
922*22db1728SEd Tanous                       "VirtualMedia.EjectMedia")
923*22db1728SEd Tanous         .privileges({"ConfigureManager"})
924*22db1728SEd Tanous         .methods(boost::beast::http::verb::post)(
925*22db1728SEd Tanous             [](const crow::Request& req,
926*22db1728SEd Tanous                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
927*22db1728SEd Tanous                const std::string& name, const std::string& resName) {
928107077deSPrzemyslaw Czarnowski                 if (name != "bmc")
929107077deSPrzemyslaw Czarnowski                 {
930*22db1728SEd Tanous                     messages::resourceNotFound(asyncResp->res,
931*22db1728SEd Tanous                                                "VirtualMedia.Eject", resName);
932*22db1728SEd Tanous 
933*22db1728SEd Tanous                     return;
934*22db1728SEd Tanous                 }
935*22db1728SEd Tanous 
936*22db1728SEd Tanous                 crow::connections::systemBus->async_method_call(
937*22db1728SEd Tanous                     [asyncResp, req,
938*22db1728SEd Tanous                      resName](const boost::system::error_code ec,
939*22db1728SEd Tanous                               const GetObjectType& getObjectType) {
940*22db1728SEd Tanous                         if (ec)
941*22db1728SEd Tanous                         {
942*22db1728SEd Tanous                             BMCWEB_LOG_ERROR
943*22db1728SEd Tanous                                 << "ObjectMapper::GetObject call failed: "
944*22db1728SEd Tanous                                 << ec;
945*22db1728SEd Tanous                             messages::internalError(asyncResp->res);
946*22db1728SEd Tanous 
947*22db1728SEd Tanous                             return;
948*22db1728SEd Tanous                         }
949*22db1728SEd Tanous                         std::string service = getObjectType.begin()->first;
950*22db1728SEd Tanous                         BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
951*22db1728SEd Tanous 
952*22db1728SEd Tanous                         crow::connections::systemBus->async_method_call(
953*22db1728SEd Tanous                             [resName, service, req, asyncResp{asyncResp}](
954*22db1728SEd Tanous                                 const boost::system::error_code ec,
955*22db1728SEd Tanous                                 ManagedObjectType& subtree) {
956*22db1728SEd Tanous                                 if (ec)
957*22db1728SEd Tanous                                 {
958*22db1728SEd Tanous                                     BMCWEB_LOG_DEBUG << "DBUS response error";
959*22db1728SEd Tanous 
960*22db1728SEd Tanous                                     return;
961*22db1728SEd Tanous                                 }
962*22db1728SEd Tanous 
963*22db1728SEd Tanous                                 for (const auto& object : subtree)
964*22db1728SEd Tanous                                 {
965*22db1728SEd Tanous                                     const std::string& path =
966*22db1728SEd Tanous                                         static_cast<const std::string&>(
967*22db1728SEd Tanous                                             object.first);
968*22db1728SEd Tanous 
969*22db1728SEd Tanous                                     std::size_t lastIndex = path.rfind('/');
970*22db1728SEd Tanous                                     if (lastIndex == std::string::npos)
971*22db1728SEd Tanous                                     {
972*22db1728SEd Tanous                                         continue;
973*22db1728SEd Tanous                                     }
974*22db1728SEd Tanous 
975*22db1728SEd Tanous                                     lastIndex += 1;
976*22db1728SEd Tanous 
977*22db1728SEd Tanous                                     if (path.substr(lastIndex) == resName)
978*22db1728SEd Tanous                                     {
979*22db1728SEd Tanous                                         lastIndex = path.rfind("Proxy");
980*22db1728SEd Tanous                                         if (lastIndex != std::string::npos)
981*22db1728SEd Tanous                                         {
982*22db1728SEd Tanous                                             // Proxy mode
983*22db1728SEd Tanous                                             doVmAction(asyncResp, service,
984*22db1728SEd Tanous                                                        resName, false);
985*22db1728SEd Tanous                                         }
986*22db1728SEd Tanous 
987*22db1728SEd Tanous                                         lastIndex = path.rfind("Legacy");
988*22db1728SEd Tanous                                         if (lastIndex != std::string::npos)
989*22db1728SEd Tanous                                         {
990*22db1728SEd Tanous                                             // Legacy mode
991*22db1728SEd Tanous                                             doVmAction(asyncResp, service,
992*22db1728SEd Tanous                                                        resName, true);
993*22db1728SEd Tanous                                         }
994*22db1728SEd Tanous 
995*22db1728SEd Tanous                                         return;
996*22db1728SEd Tanous                                     }
997*22db1728SEd Tanous                                 }
998*22db1728SEd Tanous                                 BMCWEB_LOG_DEBUG << "Parent item not found";
999*22db1728SEd Tanous                                 messages::resourceNotFound(
1000*22db1728SEd Tanous                                     asyncResp->res, "VirtualMedia", resName);
1001*22db1728SEd Tanous                             },
1002*22db1728SEd Tanous                             service, "/xyz/openbmc_project/VirtualMedia",
1003*22db1728SEd Tanous                             "org.freedesktop.DBus.ObjectManager",
1004*22db1728SEd Tanous                             "GetManagedObjects");
1005*22db1728SEd Tanous                     },
1006*22db1728SEd Tanous                     "xyz.openbmc_project.ObjectMapper",
1007*22db1728SEd Tanous                     "/xyz/openbmc_project/object_mapper",
1008*22db1728SEd Tanous                     "xyz.openbmc_project.ObjectMapper", "GetObject",
1009*22db1728SEd Tanous                     "/xyz/openbmc_project/VirtualMedia",
1010*22db1728SEd Tanous                     std::array<const char*, 0>());
1011*22db1728SEd Tanous             });
1012*22db1728SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
1013*22db1728SEd Tanous         .privileges({"Login"})
1014*22db1728SEd Tanous         .methods(boost::beast::http::verb::get)(
1015*22db1728SEd Tanous             [](const crow::Request& /* req */,
1016*22db1728SEd Tanous                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1017*22db1728SEd Tanous                const std::string& name) {
1018*22db1728SEd Tanous                 if (name != "bmc")
1019*22db1728SEd Tanous                 {
1020*22db1728SEd Tanous                     messages::resourceNotFound(asyncResp->res, "VirtualMedia",
1021*22db1728SEd Tanous                                                name);
1022107077deSPrzemyslaw Czarnowski 
1023107077deSPrzemyslaw Czarnowski                     return;
1024107077deSPrzemyslaw Czarnowski                 }
1025107077deSPrzemyslaw Czarnowski 
10268d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.type"] =
1027107077deSPrzemyslaw Czarnowski                     "#VirtualMediaCollection.VirtualMediaCollection";
10288d1b46d7Szhanghch05                 asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
10298d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.id"] =
1030d6c414f3SPrzemyslaw Czarnowski                     "/redfish/v1/Managers/" + name + "/VirtualMedia";
1031107077deSPrzemyslaw Czarnowski 
1032107077deSPrzemyslaw Czarnowski                 crow::connections::systemBus->async_method_call(
1033107077deSPrzemyslaw Czarnowski                     [asyncResp, name](const boost::system::error_code ec,
1034107077deSPrzemyslaw Czarnowski                                       const GetObjectType& getObjectType) {
1035107077deSPrzemyslaw Czarnowski                         if (ec)
1036107077deSPrzemyslaw Czarnowski                         {
1037*22db1728SEd Tanous                             BMCWEB_LOG_ERROR
1038*22db1728SEd Tanous                                 << "ObjectMapper::GetObject call failed: "
1039107077deSPrzemyslaw Czarnowski                                 << ec;
1040107077deSPrzemyslaw Czarnowski                             messages::internalError(asyncResp->res);
1041107077deSPrzemyslaw Czarnowski 
1042107077deSPrzemyslaw Czarnowski                             return;
1043107077deSPrzemyslaw Czarnowski                         }
1044107077deSPrzemyslaw Czarnowski                         std::string service = getObjectType.begin()->first;
1045107077deSPrzemyslaw Czarnowski                         BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1046107077deSPrzemyslaw Czarnowski 
1047107077deSPrzemyslaw Czarnowski                         getVmResourceList(asyncResp, service, name);
1048107077deSPrzemyslaw Czarnowski                     },
1049107077deSPrzemyslaw Czarnowski                     "xyz.openbmc_project.ObjectMapper",
1050107077deSPrzemyslaw Czarnowski                     "/xyz/openbmc_project/object_mapper",
1051107077deSPrzemyslaw Czarnowski                     "xyz.openbmc_project.ObjectMapper", "GetObject",
1052*22db1728SEd Tanous                     "/xyz/openbmc_project/VirtualMedia",
1053*22db1728SEd Tanous                     std::array<const char*, 0>());
1054*22db1728SEd Tanous             });
1055107077deSPrzemyslaw Czarnowski 
1056*22db1728SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
1057*22db1728SEd Tanous         .privileges({"Login"})
1058*22db1728SEd Tanous         .methods(boost::beast::http::verb::get)(
1059*22db1728SEd Tanous             [](const crow::Request& /* req */,
1060*22db1728SEd Tanous                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1061*22db1728SEd Tanous                const std::string& name, const std::string& resName) {
1062107077deSPrzemyslaw Czarnowski                 if (name != "bmc")
1063107077deSPrzemyslaw Czarnowski                 {
1064*22db1728SEd Tanous                     messages::resourceNotFound(asyncResp->res, "VirtualMedia",
1065*22db1728SEd Tanous                                                resName);
1066107077deSPrzemyslaw Czarnowski 
1067107077deSPrzemyslaw Czarnowski                     return;
1068107077deSPrzemyslaw Czarnowski                 }
1069107077deSPrzemyslaw Czarnowski 
1070107077deSPrzemyslaw Czarnowski                 crow::connections::systemBus->async_method_call(
1071*22db1728SEd Tanous                     [asyncResp, name,
1072*22db1728SEd Tanous                      resName](const boost::system::error_code ec,
1073107077deSPrzemyslaw Czarnowski                               const GetObjectType& getObjectType) {
1074107077deSPrzemyslaw Czarnowski                         if (ec)
1075107077deSPrzemyslaw Czarnowski                         {
1076*22db1728SEd Tanous                             BMCWEB_LOG_ERROR
1077*22db1728SEd Tanous                                 << "ObjectMapper::GetObject call failed: "
1078107077deSPrzemyslaw Czarnowski                                 << ec;
1079107077deSPrzemyslaw Czarnowski                             messages::internalError(asyncResp->res);
1080107077deSPrzemyslaw Czarnowski 
1081107077deSPrzemyslaw Czarnowski                             return;
1082107077deSPrzemyslaw Czarnowski                         }
1083107077deSPrzemyslaw Czarnowski                         std::string service = getObjectType.begin()->first;
1084107077deSPrzemyslaw Czarnowski                         BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1085107077deSPrzemyslaw Czarnowski 
1086107077deSPrzemyslaw Czarnowski                         getVmData(asyncResp, service, name, resName);
1087107077deSPrzemyslaw Czarnowski                     },
1088107077deSPrzemyslaw Czarnowski                     "xyz.openbmc_project.ObjectMapper",
1089107077deSPrzemyslaw Czarnowski                     "/xyz/openbmc_project/object_mapper",
1090107077deSPrzemyslaw Czarnowski                     "xyz.openbmc_project.ObjectMapper", "GetObject",
1091*22db1728SEd Tanous                     "/xyz/openbmc_project/VirtualMedia",
1092*22db1728SEd Tanous                     std::array<const char*, 0>());
1093*22db1728SEd Tanous             });
1094107077deSPrzemyslaw Czarnowski }
1095107077deSPrzemyslaw Czarnowski 
1096107077deSPrzemyslaw Czarnowski } // namespace redfish
1097