blob: 00b4223fdf3df1ac5aac87a3312e26c6263af422 [file] [log] [blame]
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "account_service.hpp"
19#include "app.hpp"
George Liu2b731192023-01-11 16:27:13 +080020#include "dbus_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080021#include "query.hpp"
22#include "registries/privilege_registry.hpp"
23#include "utils/json_utils.hpp"
24
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +010025#include <boost/process/async_pipe.hpp>
26#include <boost/type_traits/has_dereference.hpp>
Anna Platash9e319cf2020-11-17 10:18:31 +010027#include <boost/url/url_view.hpp>
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020028
George Liu2b731192023-01-11 16:27:13 +080029#include <array>
30#include <string_view>
31
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020032namespace redfish
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020033{
Anna Platash9e319cf2020-11-17 10:18:31 +010034/**
35 * @brief Function extracts transfer protocol name from URI.
36 */
Ed Tanous67df0732021-10-26 11:23:56 -070037inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
38{
39 boost::urls::result<boost::urls::url_view> url =
Ed Tanous079360a2022-06-29 10:05:19 -070040 boost::urls::parse_uri(imageUri);
Ed Tanous67df0732021-10-26 11:23:56 -070041 if (!url)
42 {
43 return "None";
44 }
Ed Tanous079360a2022-06-29 10:05:19 -070045 std::string_view scheme = url->scheme();
Ed Tanous67df0732021-10-26 11:23:56 -070046 if (scheme == "smb")
47 {
48 return "CIFS";
49 }
50 if (scheme == "https")
51 {
52 return "HTTPS";
53 }
54
55 return "None";
56}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020057
58/**
59 * @brief Read all known properties from VM object interfaces
60 */
Ed Tanous22db1722021-06-09 10:53:51 -070061inline void
Ed Tanous8a592812022-06-04 09:06:59 -070062 vmParseInterfaceObject(const dbus::utility::DBusInteracesMap& interfaces,
zhanghch058d1b46d2021-04-01 11:18:24 +080063 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020064{
Ed Tanous8a592812022-06-04 09:06:59 -070065 for (const auto& [interface, values] : interfaces)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020066 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080067 if (interface == "xyz.openbmc_project.VirtualMedia.MountPoint")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020068 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080069 for (const auto& [property, value] : values)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020070 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080071 if (property == "EndpointId")
72 {
73 const std::string* endpointIdValue =
74 std::get_if<std::string>(&value);
75 if (endpointIdValue == nullptr)
76 {
77 continue;
78 }
79 if (!endpointIdValue->empty())
80 {
81 // Proxy mode
82 aResp->res
83 .jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
84 *endpointIdValue;
85 aResp->res.jsonValue["TransferProtocolType"] = "OEM";
86 }
87 }
88 if (property == "ImageURL")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020089 {
Anna Platash9e319cf2020-11-17 10:18:31 +010090 const std::string* imageUrlValue =
Ed Tanous711ac7a2021-12-20 09:34:41 -080091 std::get_if<std::string>(&value);
Ed Tanous26f69762022-01-25 09:49:11 -080092 if (imageUrlValue != nullptr && !imageUrlValue->empty())
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +010093 {
Anna Platash9e319cf2020-11-17 10:18:31 +010094 std::filesystem::path filePath = *imageUrlValue;
95 if (!filePath.has_filename())
96 {
97 // this will handle https share, which not
98 // necessarily has to have filename given.
99 aResp->res.jsonValue["ImageName"] = "";
100 }
101 else
102 {
103 aResp->res.jsonValue["ImageName"] =
104 filePath.filename();
105 }
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100106
Anna Platash9e319cf2020-11-17 10:18:31 +0100107 aResp->res.jsonValue["Image"] = *imageUrlValue;
Anna Platash9e319cf2020-11-17 10:18:31 +0100108 aResp->res.jsonValue["TransferProtocolType"] =
109 getTransferProtocolTypeFromUri(*imageUrlValue);
110
Ed Tanous711ac7a2021-12-20 09:34:41 -0800111 aResp->res.jsonValue["ConnectedVia"] = "URI";
Anna Platash9e319cf2020-11-17 10:18:31 +0100112 }
113 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800114 if (property == "WriteProtected")
Anna Platash9e319cf2020-11-17 10:18:31 +0100115 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800116 const bool* writeProtectedValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800117 if (writeProtectedValue != nullptr)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200118 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100119 aResp->res.jsonValue["WriteProtected"] =
120 *writeProtectedValue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200121 }
122 }
123 }
124 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800125 if (interface == "xyz.openbmc_project.VirtualMedia.Process")
126 {
127 for (const auto& [property, value] : values)
128 {
129 if (property == "Active")
130 {
131 const bool* activeValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800132 if (activeValue == nullptr)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800133 {
134 BMCWEB_LOG_DEBUG << "Value Active not found";
135 return;
136 }
137 aResp->res.jsonValue["Inserted"] = *activeValue;
138
Ed Tanouse05aec52022-01-25 10:28:56 -0800139 if (*activeValue)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800140 {
141 aResp->res.jsonValue["ConnectedVia"] = "Applet";
142 }
143 }
144 }
145 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200146 }
147}
148
149/**
150 * @brief Fill template for Virtual Media Item.
151 */
Ed Tanous22db1722021-06-09 10:53:51 -0700152inline nlohmann::json vmItemTemplate(const std::string& name,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500153 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200154{
155 nlohmann::json item;
Ed Tanousfdb20342022-06-03 09:56:52 -0700156 item["@odata.id"] = crow::utility::urlFromPieces(
157 "redfish", "v1", "Managers", name, "VirtualMedia", resName);
Ed Tanous22db1722021-06-09 10:53:51 -0700158
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100159 item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200160 item["Name"] = "Virtual Removable Media";
161 item["Id"] = resName;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200162 item["WriteProtected"] = true;
Ed Tanous613dabe2022-07-09 11:17:36 -0700163 item["MediaTypes"] = nlohmann::json::array_t({"CD", "USBStick"});
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200164 item["TransferMethod"] = "Stream";
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100165 item["Oem"]["OpenBMC"]["@odata.type"] =
166 "#OemVirtualMedia.v1_0_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200167
168 return item;
169}
170
171/**
172 * @brief Fills collection data
173 */
Ed Tanous22db1722021-06-09 10:53:51 -0700174inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500175 const std::string& service,
176 const std::string& name)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200177{
178 BMCWEB_LOG_DEBUG << "Get available Virtual Media resources.";
179 crow::connections::systemBus->async_method_call(
Ed Tanous02cad962022-06-30 16:50:15 -0700180 [name, aResp{std::move(aResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800181 const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700182 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700183 if (ec)
184 {
185 BMCWEB_LOG_DEBUG << "DBUS response error";
186 return;
187 }
188 nlohmann::json& members = aResp->res.jsonValue["Members"];
189 members = nlohmann::json::array();
190
191 for (const auto& object : subtree)
192 {
193 nlohmann::json item;
194 std::string path = object.first.filename();
195 if (path.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200196 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700197 continue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200198 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200199
Ed Tanousfdb20342022-06-03 09:56:52 -0700200 item["@odata.id"] = crow::utility::urlFromPieces(
201 "redfish", "v1", "Managers", name, "VirtualMedia", path);
Ed Tanous002d39b2022-05-31 08:59:27 -0700202 members.emplace_back(std::move(item));
203 }
204 aResp->res.jsonValue["Members@odata.count"] = members.size();
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200205 },
206 service, "/xyz/openbmc_project/VirtualMedia",
207 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
208}
209
210/**
211 * @brief Fills data for specific resource
212 */
Ed Tanous22db1722021-06-09 10:53:51 -0700213inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500214 const std::string& service, const std::string& name,
215 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200216{
217 BMCWEB_LOG_DEBUG << "Get Virtual Media resource data.";
218
219 crow::connections::systemBus->async_method_call(
Ed Tanous914e2d52022-01-07 11:38:34 -0800220 [resName, name,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800221 aResp](const boost::system::error_code& ec,
Ed Tanous914e2d52022-01-07 11:38:34 -0800222 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700223 if (ec)
224 {
225 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200226
Ed Tanous002d39b2022-05-31 08:59:27 -0700227 return;
228 }
229
230 for (const auto& item : subtree)
231 {
232 std::string thispath = item.first.filename();
233 if (thispath.empty())
234 {
235 continue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200236 }
237
Ed Tanous002d39b2022-05-31 08:59:27 -0700238 if (thispath != resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200239 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700240 continue;
241 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200242
Ed Tanous002d39b2022-05-31 08:59:27 -0700243 // "Legacy"/"Proxy"
244 auto mode = item.first.parent_path();
245 // "VirtualMedia"
246 auto type = mode.parent_path();
247 if (mode.filename().empty() || type.filename().empty())
248 {
249 continue;
250 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200251
Ed Tanous002d39b2022-05-31 08:59:27 -0700252 if (type.filename() != "VirtualMedia")
253 {
254 continue;
255 }
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200256
Ed Tanous002d39b2022-05-31 08:59:27 -0700257 aResp->res.jsonValue = vmItemTemplate(name, resName);
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200258
Ed Tanous002d39b2022-05-31 08:59:27 -0700259 // Check if dbus path is Legacy type
260 if (mode.filename() == "Legacy")
261 {
262 aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
Ed Tanousfdb20342022-06-03 09:56:52 -0700263 ["target"] = crow::utility::urlFromPieces(
264 "redfish", "v1", "Managers", name, "VirtualMedia", resName,
265 "Actions", "VirtualMedia.InsertMedia");
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200266 }
267
Ed Tanous002d39b2022-05-31 08:59:27 -0700268 vmParseInterfaceObject(item.second, aResp);
269
270 aResp->res
271 .jsonValue["Actions"]["#VirtualMedia.EjectMedia"]["target"] =
Ed Tanousfdb20342022-06-03 09:56:52 -0700272 crow::utility::urlFromPieces("redfish", "v1", "Managers", name,
273 "VirtualMedia", resName, "Actions",
274 "VirtualMedia.EjectMedia");
Ed Tanous002d39b2022-05-31 08:59:27 -0700275 return;
276 }
277
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +0800278 messages::resourceNotFound(aResp->res, "VirtualMedia", resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200279 },
280 service, "/xyz/openbmc_project/VirtualMedia",
281 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
282}
283
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200284/**
Ed Tanous22db1722021-06-09 10:53:51 -0700285 * @brief Transfer protocols supported for InsertMedia action.
286 *
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200287 */
Ed Tanous22db1722021-06-09 10:53:51 -0700288enum class TransferProtocol
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200289{
Ed Tanous22db1722021-06-09 10:53:51 -0700290 https,
291 smb,
292 invalid
293};
294
295/**
296 * @brief Function extracts transfer protocol type from URI.
297 *
298 */
Ed Tanous67df0732021-10-26 11:23:56 -0700299inline std::optional<TransferProtocol>
Ed Tanousace85d62021-10-26 12:45:59 -0700300 getTransferProtocolFromUri(const boost::urls::url_view& imageUri)
Ed Tanous67df0732021-10-26 11:23:56 -0700301{
Ed Tanous079360a2022-06-29 10:05:19 -0700302 std::string_view scheme = imageUri.scheme();
Ed Tanous67df0732021-10-26 11:23:56 -0700303 if (scheme == "smb")
304 {
305 return TransferProtocol::smb;
306 }
307 if (scheme == "https")
308 {
309 return TransferProtocol::https;
310 }
311 if (!scheme.empty())
312 {
313 return TransferProtocol::invalid;
314 }
315
316 return {};
317}
Ed Tanous22db1722021-06-09 10:53:51 -0700318
319/**
320 * @brief Function convert transfer protocol from string param.
321 *
322 */
323inline std::optional<TransferProtocol> getTransferProtocolFromParam(
324 const std::optional<std::string>& transferProtocolType)
325{
326 if (transferProtocolType == std::nullopt)
Agata Olenderc6f4e012020-03-11 15:19:07 +0100327 {
Ed Tanous22db1722021-06-09 10:53:51 -0700328 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100329 }
330
Ed Tanous22db1722021-06-09 10:53:51 -0700331 if (*transferProtocolType == "CIFS")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200332 {
Ed Tanous22db1722021-06-09 10:53:51 -0700333 return TransferProtocol::smb;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200334 }
335
Ed Tanous22db1722021-06-09 10:53:51 -0700336 if (*transferProtocolType == "HTTPS")
337 {
338 return TransferProtocol::https;
339 }
340
341 return TransferProtocol::invalid;
342}
343
344/**
345 * @brief Function extends URI with transfer protocol type.
346 *
347 */
348inline std::string
349 getUriWithTransferProtocol(const std::string& imageUri,
350 const TransferProtocol& transferProtocol)
351{
352 if (transferProtocol == TransferProtocol::smb)
353 {
354 return "smb://" + imageUri;
355 }
356
357 if (transferProtocol == TransferProtocol::https)
358 {
359 return "https://" + imageUri;
360 }
361
362 return imageUri;
363}
364
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200365struct InsertMediaActionParams
366{
367 std::string imageUrl;
368 std::optional<std::string> userName;
369 std::optional<std::string> password;
370 std::optional<std::string> transferMethod;
371 std::optional<std::string> transferProtocolType;
372 std::optional<bool> writeProtected = true;
373 std::optional<bool> inserted;
374};
375
Ed Tanous22db1722021-06-09 10:53:51 -0700376/**
377 * @brief Function validate parameters of insert media request.
378 *
379 */
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200380inline bool validateParams(crow::Response& res,
381 InsertMediaActionParams& actionParams)
Ed Tanous22db1722021-06-09 10:53:51 -0700382{
383 BMCWEB_LOG_DEBUG << "Validation started";
384 // required param imageUrl must not be empty
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200385 if (actionParams.imageUrl.empty())
Ed Tanous22db1722021-06-09 10:53:51 -0700386 {
387 BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
388
389 messages::propertyValueFormatError(res, "<empty>", "Image");
390
391 return false;
392 }
393
394 // optional param inserted must be true
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200395 if ((actionParams.inserted != std::nullopt) && !*actionParams.inserted)
Ed Tanous22db1722021-06-09 10:53:51 -0700396 {
397 BMCWEB_LOG_ERROR
398 << "Request action optional parameter Inserted must be true.";
399
400 messages::actionParameterNotSupported(res, "Inserted", "InsertMedia");
401
402 return false;
403 }
404
405 // optional param transferMethod must be stream
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200406 if ((actionParams.transferMethod != std::nullopt) &&
407 (*actionParams.transferMethod != "Stream"))
Ed Tanous22db1722021-06-09 10:53:51 -0700408 {
409 BMCWEB_LOG_ERROR << "Request action optional parameter "
410 "TransferMethod must be Stream.";
411
412 messages::actionParameterNotSupported(res, "TransferMethod",
413 "InsertMedia");
414
415 return false;
416 }
Ed Tanousace85d62021-10-26 12:45:59 -0700417 boost::urls::result<boost::urls::url_view> url =
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200418 boost::urls::parse_uri(boost::string_view(actionParams.imageUrl));
Ed Tanousace85d62021-10-26 12:45:59 -0700419 if (!url)
420 {
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200421 messages::actionParameterValueFormatError(res, actionParams.imageUrl,
422 "Image", "InsertMedia");
Michal Orzel9bc55692022-06-14 15:50:50 +0200423 return false;
Ed Tanousace85d62021-10-26 12:45:59 -0700424 }
Ed Tanous22db1722021-06-09 10:53:51 -0700425 std::optional<TransferProtocol> uriTransferProtocolType =
Ed Tanousace85d62021-10-26 12:45:59 -0700426 getTransferProtocolFromUri(*url);
Ed Tanous22db1722021-06-09 10:53:51 -0700427
428 std::optional<TransferProtocol> paramTransferProtocolType =
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200429 getTransferProtocolFromParam(actionParams.transferProtocolType);
Ed Tanous22db1722021-06-09 10:53:51 -0700430
431 // ImageUrl does not contain valid protocol type
432 if (*uriTransferProtocolType == TransferProtocol::invalid)
433 {
434 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
435 "contain specified protocol type from list: "
436 "(smb, https).";
437
Ed Tanousace85d62021-10-26 12:45:59 -0700438 messages::resourceAtUriInUnknownFormat(res, *url);
Ed Tanous22db1722021-06-09 10:53:51 -0700439
440 return false;
441 }
442
443 // transferProtocolType should contain value from list
444 if (*paramTransferProtocolType == TransferProtocol::invalid)
445 {
446 BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
447 "must be provided with value from list: "
448 "(CIFS, HTTPS).";
449
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200450 messages::propertyValueNotInList(
451 res, *actionParams.transferProtocolType, "TransferProtocolType");
Ed Tanous22db1722021-06-09 10:53:51 -0700452 return false;
453 }
454
455 // valid transfer protocol not provided either with URI nor param
456 if ((uriTransferProtocolType == std::nullopt) &&
457 (paramTransferProtocolType == std::nullopt))
458 {
459 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
460 "contain specified protocol type or param "
461 "TransferProtocolType must be provided.";
462
Ed Tanousace85d62021-10-26 12:45:59 -0700463 messages::resourceAtUriInUnknownFormat(res, *url);
Ed Tanous22db1722021-06-09 10:53:51 -0700464
465 return false;
466 }
467
468 // valid transfer protocol provided both with URI and param
469 if ((paramTransferProtocolType != std::nullopt) &&
470 (uriTransferProtocolType != std::nullopt))
471 {
472 // check if protocol is the same for URI and param
473 if (*paramTransferProtocolType != *uriTransferProtocolType)
474 {
475 BMCWEB_LOG_ERROR << "Request action parameter "
476 "TransferProtocolType must contain the "
477 "same protocol type as protocol type "
478 "provided with param imageUrl.";
479
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200480 messages::actionParameterValueTypeError(
481 res, *actionParams.transferProtocolType, "TransferProtocolType",
482 "InsertMedia");
Ed Tanous22db1722021-06-09 10:53:51 -0700483
484 return false;
485 }
486 }
487
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200488 // validation passed, add protocol to URI if needed
Ed Tanous22db1722021-06-09 10:53:51 -0700489 if (uriTransferProtocolType == std::nullopt)
490 {
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200491 actionParams.imageUrl = getUriWithTransferProtocol(
492 actionParams.imageUrl, *paramTransferProtocolType);
Ed Tanous22db1722021-06-09 10:53:51 -0700493 }
494
495 return true;
496}
497
498template <typename T>
499static void secureCleanup(T& value)
500{
Ed Tanous4ecc6182022-01-07 09:36:26 -0800501 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
Ed Tanous22db1722021-06-09 10:53:51 -0700502 auto raw = const_cast<typename T::value_type*>(value.data());
503 explicit_bzero(raw, value.size() * sizeof(*raw));
504}
505
506class Credentials
507{
508 public:
509 Credentials(std::string&& user, std::string&& password) :
510 userBuf(std::move(user)), passBuf(std::move(password))
511 {}
512
513 ~Credentials()
514 {
515 secureCleanup(userBuf);
516 secureCleanup(passBuf);
517 }
518
519 const std::string& user()
520 {
521 return userBuf;
522 }
523
524 const std::string& password()
525 {
526 return passBuf;
527 }
528
529 Credentials() = delete;
530 Credentials(const Credentials&) = delete;
531 Credentials& operator=(const Credentials&) = delete;
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800532 Credentials(Credentials&&) = delete;
533 Credentials& operator=(Credentials&&) = delete;
Ed Tanous22db1722021-06-09 10:53:51 -0700534
535 private:
536 std::string userBuf;
537 std::string passBuf;
538};
539
540class CredentialsProvider
541{
542 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500543 template <typename T>
Ed Tanous22db1722021-06-09 10:53:51 -0700544 struct Deleter
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100545 {
Ed Tanous22db1722021-06-09 10:53:51 -0700546 void operator()(T* buff) const
547 {
548 if (buff)
549 {
550 secureCleanup(*buff);
551 delete buff;
552 }
553 }
554 };
555
556 using Buffer = std::vector<char>;
557 using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
558 // Using explicit definition instead of std::function to avoid implicit
559 // conversions eg. stack copy instead of reference
560 using FormatterFunc = void(const std::string& username,
561 const std::string& password, Buffer& dest);
562
563 CredentialsProvider(std::string&& user, std::string&& password) :
564 credentials(std::move(user), std::move(password))
565 {}
566
567 const std::string& user()
568 {
569 return credentials.user();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100570 }
571
Ed Tanous22db1722021-06-09 10:53:51 -0700572 const std::string& password()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100573 {
Ed Tanous22db1722021-06-09 10:53:51 -0700574 return credentials.password();
575 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100576
Ed Tanous1917ee92022-06-30 22:30:50 -0700577 SecureBuffer pack(FormatterFunc* formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100578 {
Ed Tanous22db1722021-06-09 10:53:51 -0700579 SecureBuffer packed{new Buffer{}};
Ed Tanouse662eae2022-01-25 10:39:19 -0800580 if (formatter != nullptr)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100581 {
Ed Tanous22db1722021-06-09 10:53:51 -0700582 formatter(credentials.user(), credentials.password(), *packed);
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100583 }
584
Ed Tanous22db1722021-06-09 10:53:51 -0700585 return packed;
586 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100587
Ed Tanous22db1722021-06-09 10:53:51 -0700588 private:
589 Credentials credentials;
590};
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100591
Ed Tanous22db1722021-06-09 10:53:51 -0700592// Wrapper for boost::async_pipe ensuring proper pipe cleanup
593template <typename Buffer>
594class Pipe
595{
596 public:
597 using unix_fd = sdbusplus::message::unix_fd;
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100598
Ed Tanous8a592812022-06-04 09:06:59 -0700599 Pipe(boost::asio::io_context& io, Buffer&& bufferIn) :
600 impl(io), buffer{std::move(bufferIn)}
Ed Tanous22db1722021-06-09 10:53:51 -0700601 {}
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100602
Ed Tanous22db1722021-06-09 10:53:51 -0700603 ~Pipe()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100604 {
Ed Tanous22db1722021-06-09 10:53:51 -0700605 // Named pipe needs to be explicitly removed
606 impl.close();
607 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100608
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800609 Pipe(const Pipe&) = delete;
610 Pipe(Pipe&&) = delete;
611 Pipe& operator=(const Pipe&) = delete;
612 Pipe& operator=(Pipe&&) = delete;
613
Ed Tanous22db1722021-06-09 10:53:51 -0700614 unix_fd fd()
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200615 {
Ed Tanous22db1722021-06-09 10:53:51 -0700616 return unix_fd{impl.native_source()};
617 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100618
Ed Tanous22db1722021-06-09 10:53:51 -0700619 template <typename WriteHandler>
620 void asyncWrite(WriteHandler&& handler)
621 {
622 impl.async_write_some(data(), std::forward<WriteHandler>(handler));
623 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100624
Ed Tanous22db1722021-06-09 10:53:51 -0700625 private:
626 // Specialization for pointer types
627 template <typename B = Buffer>
628 typename std::enable_if<boost::has_dereference<B>::value,
629 boost::asio::const_buffer>::type
630 data()
631 {
632 return boost::asio::buffer(*buffer);
633 }
634
635 template <typename B = Buffer>
636 typename std::enable_if<!boost::has_dereference<B>::value,
637 boost::asio::const_buffer>::type
638 data()
639 {
640 return boost::asio::buffer(buffer);
641 }
642
643 const std::string name;
644 boost::process::async_pipe impl;
645 Buffer buffer;
646};
647
648/**
649 * @brief Function transceives data with dbus directly.
650 *
651 * All BMC state properties will be retrieved before sending reset request.
652 */
653inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
654 const std::string& service, const std::string& name,
655 const std::string& imageUrl, const bool rw,
656 std::string&& userName, std::string&& password)
657{
658 using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
659 constexpr const size_t secretLimit = 1024;
660
661 std::shared_ptr<SecurePipe> secretPipe;
Ed Tanous168e20c2021-12-13 14:39:53 -0800662 dbus::utility::DbusVariantType unixFd = -1;
Ed Tanous22db1722021-06-09 10:53:51 -0700663
664 if (!userName.empty() || !password.empty())
665 {
666 // Encapsulate in safe buffer
667 CredentialsProvider credentials(std::move(userName),
668 std::move(password));
669
670 // Payload must contain data + NULL delimiters
671 if (credentials.user().size() + credentials.password().size() + 2 >
672 secretLimit)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100673 {
Ed Tanous22db1722021-06-09 10:53:51 -0700674 BMCWEB_LOG_ERROR << "Credentials too long to handle";
675 messages::unrecognizedRequestBody(asyncResp->res);
676 return;
677 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100678
Ed Tanous22db1722021-06-09 10:53:51 -0700679 // Pack secret
680 auto secret = credentials.pack(
681 [](const auto& user, const auto& pass, auto& buff) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700682 std::copy(user.begin(), user.end(), std::back_inserter(buff));
683 buff.push_back('\0');
684 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
685 buff.push_back('\0');
686 });
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100687
Ed Tanous22db1722021-06-09 10:53:51 -0700688 // Open pipe
689 secretPipe = std::make_shared<SecurePipe>(
690 crow::connections::systemBus->get_io_context(), std::move(secret));
691 unixFd = secretPipe->fd();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100692
Ed Tanous22db1722021-06-09 10:53:51 -0700693 // Pass secret over pipe
694 secretPipe->asyncWrite(
695 [asyncResp](const boost::system::error_code& ec, std::size_t) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700696 if (ec)
697 {
698 BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
699 messages::internalError(asyncResp->res);
700 }
701 });
Ed Tanous22db1722021-06-09 10:53:51 -0700702 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100703
Ed Tanous22db1722021-06-09 10:53:51 -0700704 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800705 [asyncResp, secretPipe](const boost::system::error_code& ec,
Ed Tanous22db1722021-06-09 10:53:51 -0700706 bool success) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700707 if (ec)
708 {
709 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
710 messages::internalError(asyncResp->res);
711 }
712 else if (!success)
713 {
714 BMCWEB_LOG_ERROR << "Service responded with error";
715 messages::generalError(asyncResp->res);
716 }
Ed Tanous22db1722021-06-09 10:53:51 -0700717 },
718 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
719 "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
720 unixFd);
721}
722
723/**
724 * @brief Function transceives data with dbus directly.
725 *
726 * All BMC state properties will be retrieved before sending reset request.
727 */
728inline void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
729 const std::string& service, const std::string& name,
730 bool legacy)
731{
732
733 // Legacy mount requires parameter with image
734 if (legacy)
735 {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100736 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800737 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700738 if (ec)
739 {
740 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700741
Ed Tanous002d39b2022-05-31 08:59:27 -0700742 messages::internalError(asyncResp->res);
743 return;
744 }
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100745 },
746 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
Ed Tanous22db1722021-06-09 10:53:51 -0700747 "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200748 }
Ed Tanous22db1722021-06-09 10:53:51 -0700749 else // proxy
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200750 {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200751 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800752 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700753 if (ec)
754 {
755 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700756
Ed Tanous002d39b2022-05-31 08:59:27 -0700757 messages::internalError(asyncResp->res);
758 return;
759 }
Ed Tanous22db1722021-06-09 10:53:51 -0700760 },
761 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
762 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
763 }
764}
765
Ed Tanous96825be2022-06-03 09:43:38 -0700766inline void handleManagersVirtualMediaActionInsertPost(
767 crow::App& app, const crow::Request& req,
768 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
769 const std::string& name, const std::string& resName)
770{
771 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
772 {
773 return;
774 }
775 if (name != "bmc")
776 {
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200777 messages::resourceNotFound(asyncResp->res, "VirtualMedia.InsertMedia",
Ed Tanous96825be2022-06-03 09:43:38 -0700778 resName);
779
780 return;
781 }
782 InsertMediaActionParams actionParams;
783
784 // Read obligatory parameters (url of
785 // image)
786 if (!json_util::readJsonAction(
787 req, asyncResp->res, "Image", actionParams.imageUrl,
788 "WriteProtected", actionParams.writeProtected, "UserName",
789 actionParams.userName, "Password", actionParams.password,
790 "Inserted", actionParams.inserted, "TransferMethod",
791 actionParams.transferMethod, "TransferProtocolType",
792 actionParams.transferProtocolType))
793 {
794 BMCWEB_LOG_DEBUG << "Image is not provided";
795 return;
796 }
797
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200798 bool paramsValid = validateParams(asyncResp->res, actionParams);
Ed Tanous96825be2022-06-03 09:43:38 -0700799 if (!paramsValid)
800 {
801 return;
802 }
803
George Liu2b731192023-01-11 16:27:13 +0800804 dbus::utility::getDbusObject(
805 "/xyz/openbmc_project/VirtualMedia", {},
Ed Tanous96825be2022-06-03 09:43:38 -0700806 [asyncResp, actionParams,
George Liu2b731192023-01-11 16:27:13 +0800807 resName](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -0700808 const dbus::utility::MapperGetObject& getObjectType) mutable {
809 if (ec)
810 {
811 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
812 messages::internalError(asyncResp->res);
813
814 return;
815 }
816 std::string service = getObjectType.begin()->first;
817 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
818
819 crow::connections::systemBus->async_method_call(
820 [service, resName, actionParams,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800821 asyncResp](const boost::system::error_code& ec2,
Ed Tanous96825be2022-06-03 09:43:38 -0700822 dbus::utility::ManagedObjectType& subtree) mutable {
Ed Tanous8a592812022-06-04 09:06:59 -0700823 if (ec2)
Ed Tanous96825be2022-06-03 09:43:38 -0700824 {
825 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200826 messages::internalError(asyncResp->res);
Ed Tanous96825be2022-06-03 09:43:38 -0700827
828 return;
829 }
830
831 for (const auto& object : subtree)
832 {
833 const std::string& path =
834 static_cast<const std::string&>(object.first);
835
836 std::size_t lastIndex = path.rfind('/');
837 if (lastIndex == std::string::npos)
838 {
839 continue;
840 }
841
842 lastIndex += 1;
843
844 if (path.substr(lastIndex) == resName)
845 {
846 lastIndex = path.rfind("Proxy");
847 if (lastIndex != std::string::npos)
848 {
849 // Not possible in proxy mode
850 BMCWEB_LOG_DEBUG << "InsertMedia not "
851 "allowed in proxy mode";
852 messages::resourceNotFound(asyncResp->res,
853 "VirtualMedia.InsertMedia",
854 resName);
855
856 return;
857 }
858
859 lastIndex = path.rfind("Legacy");
860 if (lastIndex == std::string::npos)
861 {
862 continue;
863 }
864
865 // manager is irrelevant for
866 // VirtualMedia dbus calls
867 doMountVmLegacy(asyncResp, service, resName,
868 actionParams.imageUrl,
869 !(*actionParams.writeProtected),
870 std::move(*actionParams.userName),
871 std::move(*actionParams.password));
872
873 return;
874 }
875 }
876 BMCWEB_LOG_DEBUG << "Parent item not found";
877 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
878 },
879 service, "/xyz/openbmc_project/VirtualMedia",
880 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
George Liu2b731192023-01-11 16:27:13 +0800881 });
Ed Tanous96825be2022-06-03 09:43:38 -0700882}
883
884inline void handleManagersVirtualMediaActionEject(
885 crow::App& app, const crow::Request& req,
886 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
887 const std::string& managerName, const std::string& resName)
888{
889 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
890 {
891 return;
892 }
893 if (managerName != "bmc")
894 {
895 messages::resourceNotFound(asyncResp->res, "VirtualMedia.Eject",
896 resName);
897
898 return;
899 }
900
George Liu2b731192023-01-11 16:27:13 +0800901 dbus::utility::getDbusObject(
902 "/xyz/openbmc_project/VirtualMedia", {},
Ed Tanous96825be2022-06-03 09:43:38 -0700903 [asyncResp,
George Liu2b731192023-01-11 16:27:13 +0800904 resName](const boost::system::error_code& ec2,
Ed Tanous96825be2022-06-03 09:43:38 -0700905 const dbus::utility::MapperGetObject& getObjectType) {
Ed Tanous8a592812022-06-04 09:06:59 -0700906 if (ec2)
Ed Tanous96825be2022-06-03 09:43:38 -0700907 {
Ed Tanous8a592812022-06-04 09:06:59 -0700908 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec2;
Ed Tanous96825be2022-06-03 09:43:38 -0700909 messages::internalError(asyncResp->res);
910
911 return;
912 }
913 std::string service = getObjectType.begin()->first;
914 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
915
916 crow::connections::systemBus->async_method_call(
Ed Tanous02cad962022-06-30 16:50:15 -0700917 [resName, service, asyncResp{asyncResp}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800918 const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700919 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous96825be2022-06-03 09:43:38 -0700920 if (ec)
921 {
922 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200923 messages::internalError(asyncResp->res);
Ed Tanous96825be2022-06-03 09:43:38 -0700924
925 return;
926 }
927
928 for (const auto& object : subtree)
929 {
930 const std::string& path =
931 static_cast<const std::string&>(object.first);
932
933 std::size_t lastIndex = path.rfind('/');
934 if (lastIndex == std::string::npos)
935 {
936 continue;
937 }
938
939 lastIndex += 1;
940
941 if (path.substr(lastIndex) == resName)
942 {
943 lastIndex = path.rfind("Proxy");
944 if (lastIndex != std::string::npos)
945 {
946 // Proxy mode
947 doVmAction(asyncResp, service, resName, false);
948 }
949
950 lastIndex = path.rfind("Legacy");
951 if (lastIndex != std::string::npos)
952 {
953 // Legacy mode
954 doVmAction(asyncResp, service, resName, true);
955 }
956
957 return;
958 }
959 }
960 BMCWEB_LOG_DEBUG << "Parent item not found";
961 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
962 },
963 service, "/xyz/openbmc_project/VirtualMedia",
964 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
George Liu2b731192023-01-11 16:27:13 +0800965 });
Ed Tanous96825be2022-06-03 09:43:38 -0700966}
967
968inline void handleManagersVirtualMediaCollectionGet(
969 crow::App& app, const crow::Request& req,
970 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
971 const std::string& name)
972{
973 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
974 {
975 return;
976 }
977 if (name != "bmc")
978 {
979 messages::resourceNotFound(asyncResp->res, "VirtualMedia", name);
980
981 return;
982 }
983
984 asyncResp->res.jsonValue["@odata.type"] =
985 "#VirtualMediaCollection.VirtualMediaCollection";
986 asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
Ed Tanousfdb20342022-06-03 09:56:52 -0700987 asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
988 "redfish", "v1", "Managers", name, "VirtualMedia");
Ed Tanous96825be2022-06-03 09:43:38 -0700989
George Liu2b731192023-01-11 16:27:13 +0800990 dbus::utility::getDbusObject(
991 "/xyz/openbmc_project/VirtualMedia", {},
992 [asyncResp, name](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -0700993 const dbus::utility::MapperGetObject& getObjectType) {
994 if (ec)
995 {
996 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
997 messages::internalError(asyncResp->res);
998
999 return;
1000 }
1001 std::string service = getObjectType.begin()->first;
1002 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1003
1004 getVmResourceList(asyncResp, service, name);
George Liu2b731192023-01-11 16:27:13 +08001005 });
Ed Tanous96825be2022-06-03 09:43:38 -07001006}
1007
1008inline void
1009 handleVirtualMediaGet(crow::App& app, const crow::Request& req,
1010 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1011 const std::string& name, const std::string& resName)
1012{
1013 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1014 {
1015 return;
1016 }
1017 if (name != "bmc")
1018 {
1019 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
1020
1021 return;
1022 }
1023
George Liu2b731192023-01-11 16:27:13 +08001024 dbus::utility::getDbusObject(
1025 "/xyz/openbmc_project/VirtualMedia", {},
Ed Tanous96825be2022-06-03 09:43:38 -07001026 [asyncResp, name,
George Liu2b731192023-01-11 16:27:13 +08001027 resName](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -07001028 const dbus::utility::MapperGetObject& getObjectType) {
1029 if (ec)
1030 {
1031 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
1032 messages::internalError(asyncResp->res);
1033
1034 return;
1035 }
1036 std::string service = getObjectType.begin()->first;
1037 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1038
1039 getVmData(asyncResp, service, name, resName);
George Liu2b731192023-01-11 16:27:13 +08001040 });
Ed Tanous96825be2022-06-03 09:43:38 -07001041}
1042
Ed Tanous22db1722021-06-09 10:53:51 -07001043inline void requestNBDVirtualMediaRoutes(App& app)
1044{
George Liu0fda0f12021-11-16 10:06:17 +08001045 BMCWEB_ROUTE(
1046 app,
1047 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
Ed Tanoused398212021-06-09 17:05:54 -07001048 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous96825be2022-06-03 09:43:38 -07001049 .methods(boost::beast::http::verb::post)(std::bind_front(
1050 handleManagersVirtualMediaActionInsertPost, std::ref(app)));
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +02001051
George Liu0fda0f12021-11-16 10:06:17 +08001052 BMCWEB_ROUTE(
1053 app,
1054 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
Ed Tanoused398212021-06-09 17:05:54 -07001055 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous96825be2022-06-03 09:43:38 -07001056 .methods(boost::beast::http::verb::post)(std::bind_front(
1057 handleManagersVirtualMediaActionEject, std::ref(app)));
Ed Tanous002d39b2022-05-31 08:59:27 -07001058
Ed Tanous22db1722021-06-09 10:53:51 -07001059 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
Ed Tanoused398212021-06-09 17:05:54 -07001060 .privileges(redfish::privileges::getVirtualMediaCollection)
Ed Tanous96825be2022-06-03 09:43:38 -07001061 .methods(boost::beast::http::verb::get)(std::bind_front(
1062 handleManagersVirtualMediaCollectionGet, std::ref(app)));
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001063
Ed Tanous22db1722021-06-09 10:53:51 -07001064 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001065 .privileges(redfish::privileges::getVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -07001066 .methods(boost::beast::http::verb::get)(
Ed Tanous96825be2022-06-03 09:43:38 -07001067 std::bind_front(handleVirtualMediaGet, std::ref(app)));
Ed Tanous22db1722021-06-09 10:53:51 -07001068}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001069
1070} // namespace redfish