blob: 7c53f7e5f9251a98d5152963b7f2be06fc6f62d9 [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"
20#include "query.hpp"
21#include "registries/privilege_registry.hpp"
22#include "utils/json_utils.hpp"
23
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +010024#include <boost/process/async_pipe.hpp>
25#include <boost/type_traits/has_dereference.hpp>
Anna Platash9e319cf2020-11-17 10:18:31 +010026#include <boost/url/url_view.hpp>
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020027
28namespace redfish
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020029{
Anna Platash9e319cf2020-11-17 10:18:31 +010030/**
31 * @brief Function extracts transfer protocol name from URI.
32 */
Ed Tanous67df0732021-10-26 11:23:56 -070033inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
34{
35 boost::urls::result<boost::urls::url_view> url =
Ed Tanous079360a2022-06-29 10:05:19 -070036 boost::urls::parse_uri(imageUri);
Ed Tanous67df0732021-10-26 11:23:56 -070037 if (!url)
38 {
39 return "None";
40 }
Ed Tanous079360a2022-06-29 10:05:19 -070041 std::string_view scheme = url->scheme();
Ed Tanous67df0732021-10-26 11:23:56 -070042 if (scheme == "smb")
43 {
44 return "CIFS";
45 }
46 if (scheme == "https")
47 {
48 return "HTTPS";
49 }
50
51 return "None";
52}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020053
54/**
55 * @brief Read all known properties from VM object interfaces
56 */
Ed Tanous22db1722021-06-09 10:53:51 -070057inline void
Ed Tanous8a592812022-06-04 09:06:59 -070058 vmParseInterfaceObject(const dbus::utility::DBusInteracesMap& interfaces,
zhanghch058d1b46d2021-04-01 11:18:24 +080059 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020060{
Ed Tanous8a592812022-06-04 09:06:59 -070061 for (const auto& [interface, values] : interfaces)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020062 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080063 if (interface == "xyz.openbmc_project.VirtualMedia.MountPoint")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020064 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080065 for (const auto& [property, value] : values)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020066 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080067 if (property == "EndpointId")
68 {
69 const std::string* endpointIdValue =
70 std::get_if<std::string>(&value);
71 if (endpointIdValue == nullptr)
72 {
73 continue;
74 }
75 if (!endpointIdValue->empty())
76 {
77 // Proxy mode
78 aResp->res
79 .jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
80 *endpointIdValue;
81 aResp->res.jsonValue["TransferProtocolType"] = "OEM";
82 }
83 }
84 if (property == "ImageURL")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020085 {
Anna Platash9e319cf2020-11-17 10:18:31 +010086 const std::string* imageUrlValue =
Ed Tanous711ac7a2021-12-20 09:34:41 -080087 std::get_if<std::string>(&value);
Ed Tanous26f69762022-01-25 09:49:11 -080088 if (imageUrlValue != nullptr && !imageUrlValue->empty())
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +010089 {
Anna Platash9e319cf2020-11-17 10:18:31 +010090 std::filesystem::path filePath = *imageUrlValue;
91 if (!filePath.has_filename())
92 {
93 // this will handle https share, which not
94 // necessarily has to have filename given.
95 aResp->res.jsonValue["ImageName"] = "";
96 }
97 else
98 {
99 aResp->res.jsonValue["ImageName"] =
100 filePath.filename();
101 }
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100102
Anna Platash9e319cf2020-11-17 10:18:31 +0100103 aResp->res.jsonValue["Image"] = *imageUrlValue;
Anna Platash9e319cf2020-11-17 10:18:31 +0100104 aResp->res.jsonValue["TransferProtocolType"] =
105 getTransferProtocolTypeFromUri(*imageUrlValue);
106
Ed Tanous711ac7a2021-12-20 09:34:41 -0800107 aResp->res.jsonValue["ConnectedVia"] = "URI";
Anna Platash9e319cf2020-11-17 10:18:31 +0100108 }
109 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800110 if (property == "WriteProtected")
Anna Platash9e319cf2020-11-17 10:18:31 +0100111 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800112 const bool* writeProtectedValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800113 if (writeProtectedValue != nullptr)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200114 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100115 aResp->res.jsonValue["WriteProtected"] =
116 *writeProtectedValue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200117 }
118 }
119 }
120 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800121 if (interface == "xyz.openbmc_project.VirtualMedia.Process")
122 {
123 for (const auto& [property, value] : values)
124 {
125 if (property == "Active")
126 {
127 const bool* activeValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800128 if (activeValue == nullptr)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800129 {
130 BMCWEB_LOG_DEBUG << "Value Active not found";
131 return;
132 }
133 aResp->res.jsonValue["Inserted"] = *activeValue;
134
Ed Tanouse05aec52022-01-25 10:28:56 -0800135 if (*activeValue)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800136 {
137 aResp->res.jsonValue["ConnectedVia"] = "Applet";
138 }
139 }
140 }
141 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200142 }
143}
144
145/**
146 * @brief Fill template for Virtual Media Item.
147 */
Ed Tanous22db1722021-06-09 10:53:51 -0700148inline nlohmann::json vmItemTemplate(const std::string& name,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500149 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200150{
151 nlohmann::json item;
Ed Tanousfdb20342022-06-03 09:56:52 -0700152 item["@odata.id"] = crow::utility::urlFromPieces(
153 "redfish", "v1", "Managers", name, "VirtualMedia", resName);
Ed Tanous22db1722021-06-09 10:53:51 -0700154
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100155 item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200156 item["Name"] = "Virtual Removable Media";
157 item["Id"] = resName;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200158 item["WriteProtected"] = true;
Ed Tanous613dabe2022-07-09 11:17:36 -0700159 item["MediaTypes"] = nlohmann::json::array_t({"CD", "USBStick"});
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200160 item["TransferMethod"] = "Stream";
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100161 item["Oem"]["OpenBMC"]["@odata.type"] =
162 "#OemVirtualMedia.v1_0_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200163
164 return item;
165}
166
167/**
168 * @brief Fills collection data
169 */
Ed Tanous22db1722021-06-09 10:53:51 -0700170inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500171 const std::string& service,
172 const std::string& name)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200173{
174 BMCWEB_LOG_DEBUG << "Get available Virtual Media resources.";
175 crow::connections::systemBus->async_method_call(
Ed Tanous02cad962022-06-30 16:50:15 -0700176 [name, aResp{std::move(aResp)}](
177 const boost::system::error_code ec,
178 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700179 if (ec)
180 {
181 BMCWEB_LOG_DEBUG << "DBUS response error";
182 return;
183 }
184 nlohmann::json& members = aResp->res.jsonValue["Members"];
185 members = nlohmann::json::array();
186
187 for (const auto& object : subtree)
188 {
189 nlohmann::json item;
190 std::string path = object.first.filename();
191 if (path.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200192 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700193 continue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200194 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200195
Ed Tanousfdb20342022-06-03 09:56:52 -0700196 item["@odata.id"] = crow::utility::urlFromPieces(
197 "redfish", "v1", "Managers", name, "VirtualMedia", path);
Ed Tanous002d39b2022-05-31 08:59:27 -0700198 members.emplace_back(std::move(item));
199 }
200 aResp->res.jsonValue["Members@odata.count"] = members.size();
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200201 },
202 service, "/xyz/openbmc_project/VirtualMedia",
203 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
204}
205
206/**
207 * @brief Fills data for specific resource
208 */
Ed Tanous22db1722021-06-09 10:53:51 -0700209inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500210 const std::string& service, const std::string& name,
211 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200212{
213 BMCWEB_LOG_DEBUG << "Get Virtual Media resource data.";
214
215 crow::connections::systemBus->async_method_call(
Ed Tanous914e2d52022-01-07 11:38:34 -0800216 [resName, name,
217 aResp](const boost::system::error_code ec,
218 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700219 if (ec)
220 {
221 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200222
Ed Tanous002d39b2022-05-31 08:59:27 -0700223 return;
224 }
225
226 for (const auto& item : subtree)
227 {
228 std::string thispath = item.first.filename();
229 if (thispath.empty())
230 {
231 continue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200232 }
233
Ed Tanous002d39b2022-05-31 08:59:27 -0700234 if (thispath != resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200235 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700236 continue;
237 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200238
Ed Tanous002d39b2022-05-31 08:59:27 -0700239 // "Legacy"/"Proxy"
240 auto mode = item.first.parent_path();
241 // "VirtualMedia"
242 auto type = mode.parent_path();
243 if (mode.filename().empty() || type.filename().empty())
244 {
245 continue;
246 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200247
Ed Tanous002d39b2022-05-31 08:59:27 -0700248 if (type.filename() != "VirtualMedia")
249 {
250 continue;
251 }
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200252
Ed Tanous002d39b2022-05-31 08:59:27 -0700253 aResp->res.jsonValue = vmItemTemplate(name, resName);
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200254
Ed Tanous002d39b2022-05-31 08:59:27 -0700255 // Check if dbus path is Legacy type
256 if (mode.filename() == "Legacy")
257 {
258 aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
Ed Tanousfdb20342022-06-03 09:56:52 -0700259 ["target"] = crow::utility::urlFromPieces(
260 "redfish", "v1", "Managers", name, "VirtualMedia", resName,
261 "Actions", "VirtualMedia.InsertMedia");
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200262 }
263
Ed Tanous002d39b2022-05-31 08:59:27 -0700264 vmParseInterfaceObject(item.second, aResp);
265
266 aResp->res
267 .jsonValue["Actions"]["#VirtualMedia.EjectMedia"]["target"] =
Ed Tanousfdb20342022-06-03 09:56:52 -0700268 crow::utility::urlFromPieces("redfish", "v1", "Managers", name,
269 "VirtualMedia", resName, "Actions",
270 "VirtualMedia.EjectMedia");
Ed Tanous002d39b2022-05-31 08:59:27 -0700271 return;
272 }
273
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +0800274 messages::resourceNotFound(aResp->res, "VirtualMedia", resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200275 },
276 service, "/xyz/openbmc_project/VirtualMedia",
277 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
278}
279
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200280/**
Ed Tanous22db1722021-06-09 10:53:51 -0700281 * @brief Transfer protocols supported for InsertMedia action.
282 *
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200283 */
Ed Tanous22db1722021-06-09 10:53:51 -0700284enum class TransferProtocol
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200285{
Ed Tanous22db1722021-06-09 10:53:51 -0700286 https,
287 smb,
288 invalid
289};
290
291/**
292 * @brief Function extracts transfer protocol type from URI.
293 *
294 */
Ed Tanous67df0732021-10-26 11:23:56 -0700295inline std::optional<TransferProtocol>
Ed Tanousace85d62021-10-26 12:45:59 -0700296 getTransferProtocolFromUri(const boost::urls::url_view& imageUri)
Ed Tanous67df0732021-10-26 11:23:56 -0700297{
Ed Tanous079360a2022-06-29 10:05:19 -0700298 std::string_view scheme = imageUri.scheme();
Ed Tanous67df0732021-10-26 11:23:56 -0700299 if (scheme == "smb")
300 {
301 return TransferProtocol::smb;
302 }
303 if (scheme == "https")
304 {
305 return TransferProtocol::https;
306 }
307 if (!scheme.empty())
308 {
309 return TransferProtocol::invalid;
310 }
311
312 return {};
313}
Ed Tanous22db1722021-06-09 10:53:51 -0700314
315/**
316 * @brief Function convert transfer protocol from string param.
317 *
318 */
319inline std::optional<TransferProtocol> getTransferProtocolFromParam(
320 const std::optional<std::string>& transferProtocolType)
321{
322 if (transferProtocolType == std::nullopt)
Agata Olenderc6f4e012020-03-11 15:19:07 +0100323 {
Ed Tanous22db1722021-06-09 10:53:51 -0700324 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100325 }
326
Ed Tanous22db1722021-06-09 10:53:51 -0700327 if (*transferProtocolType == "CIFS")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200328 {
Ed Tanous22db1722021-06-09 10:53:51 -0700329 return TransferProtocol::smb;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200330 }
331
Ed Tanous22db1722021-06-09 10:53:51 -0700332 if (*transferProtocolType == "HTTPS")
333 {
334 return TransferProtocol::https;
335 }
336
337 return TransferProtocol::invalid;
338}
339
340/**
341 * @brief Function extends URI with transfer protocol type.
342 *
343 */
344inline std::string
345 getUriWithTransferProtocol(const std::string& imageUri,
346 const TransferProtocol& transferProtocol)
347{
348 if (transferProtocol == TransferProtocol::smb)
349 {
350 return "smb://" + imageUri;
351 }
352
353 if (transferProtocol == TransferProtocol::https)
354 {
355 return "https://" + imageUri;
356 }
357
358 return imageUri;
359}
360
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200361struct InsertMediaActionParams
362{
363 std::string imageUrl;
364 std::optional<std::string> userName;
365 std::optional<std::string> password;
366 std::optional<std::string> transferMethod;
367 std::optional<std::string> transferProtocolType;
368 std::optional<bool> writeProtected = true;
369 std::optional<bool> inserted;
370};
371
Ed Tanous22db1722021-06-09 10:53:51 -0700372/**
373 * @brief Function validate parameters of insert media request.
374 *
375 */
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200376inline bool validateParams(crow::Response& res,
377 InsertMediaActionParams& actionParams)
Ed Tanous22db1722021-06-09 10:53:51 -0700378{
379 BMCWEB_LOG_DEBUG << "Validation started";
380 // required param imageUrl must not be empty
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200381 if (actionParams.imageUrl.empty())
Ed Tanous22db1722021-06-09 10:53:51 -0700382 {
383 BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
384
385 messages::propertyValueFormatError(res, "<empty>", "Image");
386
387 return false;
388 }
389
390 // optional param inserted must be true
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200391 if ((actionParams.inserted != std::nullopt) && !*actionParams.inserted)
Ed Tanous22db1722021-06-09 10:53:51 -0700392 {
393 BMCWEB_LOG_ERROR
394 << "Request action optional parameter Inserted must be true.";
395
396 messages::actionParameterNotSupported(res, "Inserted", "InsertMedia");
397
398 return false;
399 }
400
401 // optional param transferMethod must be stream
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200402 if ((actionParams.transferMethod != std::nullopt) &&
403 (*actionParams.transferMethod != "Stream"))
Ed Tanous22db1722021-06-09 10:53:51 -0700404 {
405 BMCWEB_LOG_ERROR << "Request action optional parameter "
406 "TransferMethod must be Stream.";
407
408 messages::actionParameterNotSupported(res, "TransferMethod",
409 "InsertMedia");
410
411 return false;
412 }
Ed Tanousace85d62021-10-26 12:45:59 -0700413 boost::urls::result<boost::urls::url_view> url =
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200414 boost::urls::parse_uri(boost::string_view(actionParams.imageUrl));
Ed Tanousace85d62021-10-26 12:45:59 -0700415 if (!url)
416 {
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200417 messages::actionParameterValueFormatError(res, actionParams.imageUrl,
418 "Image", "InsertMedia");
Michal Orzel9bc55692022-06-14 15:50:50 +0200419 return false;
Ed Tanousace85d62021-10-26 12:45:59 -0700420 }
Ed Tanous22db1722021-06-09 10:53:51 -0700421 std::optional<TransferProtocol> uriTransferProtocolType =
Ed Tanousace85d62021-10-26 12:45:59 -0700422 getTransferProtocolFromUri(*url);
Ed Tanous22db1722021-06-09 10:53:51 -0700423
424 std::optional<TransferProtocol> paramTransferProtocolType =
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200425 getTransferProtocolFromParam(actionParams.transferProtocolType);
Ed Tanous22db1722021-06-09 10:53:51 -0700426
427 // ImageUrl does not contain valid protocol type
428 if (*uriTransferProtocolType == TransferProtocol::invalid)
429 {
430 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
431 "contain specified protocol type from list: "
432 "(smb, https).";
433
Ed Tanousace85d62021-10-26 12:45:59 -0700434 messages::resourceAtUriInUnknownFormat(res, *url);
Ed Tanous22db1722021-06-09 10:53:51 -0700435
436 return false;
437 }
438
439 // transferProtocolType should contain value from list
440 if (*paramTransferProtocolType == TransferProtocol::invalid)
441 {
442 BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
443 "must be provided with value from list: "
444 "(CIFS, HTTPS).";
445
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200446 messages::propertyValueNotInList(
447 res, *actionParams.transferProtocolType, "TransferProtocolType");
Ed Tanous22db1722021-06-09 10:53:51 -0700448 return false;
449 }
450
451 // valid transfer protocol not provided either with URI nor param
452 if ((uriTransferProtocolType == std::nullopt) &&
453 (paramTransferProtocolType == std::nullopt))
454 {
455 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
456 "contain specified protocol type or param "
457 "TransferProtocolType must be provided.";
458
Ed Tanousace85d62021-10-26 12:45:59 -0700459 messages::resourceAtUriInUnknownFormat(res, *url);
Ed Tanous22db1722021-06-09 10:53:51 -0700460
461 return false;
462 }
463
464 // valid transfer protocol provided both with URI and param
465 if ((paramTransferProtocolType != std::nullopt) &&
466 (uriTransferProtocolType != std::nullopt))
467 {
468 // check if protocol is the same for URI and param
469 if (*paramTransferProtocolType != *uriTransferProtocolType)
470 {
471 BMCWEB_LOG_ERROR << "Request action parameter "
472 "TransferProtocolType must contain the "
473 "same protocol type as protocol type "
474 "provided with param imageUrl.";
475
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200476 messages::actionParameterValueTypeError(
477 res, *actionParams.transferProtocolType, "TransferProtocolType",
478 "InsertMedia");
Ed Tanous22db1722021-06-09 10:53:51 -0700479
480 return false;
481 }
482 }
483
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200484 // validation passed, add protocol to URI if needed
Ed Tanous22db1722021-06-09 10:53:51 -0700485 if (uriTransferProtocolType == std::nullopt)
486 {
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200487 actionParams.imageUrl = getUriWithTransferProtocol(
488 actionParams.imageUrl, *paramTransferProtocolType);
Ed Tanous22db1722021-06-09 10:53:51 -0700489 }
490
491 return true;
492}
493
494template <typename T>
495static void secureCleanup(T& value)
496{
Ed Tanous4ecc6182022-01-07 09:36:26 -0800497 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
Ed Tanous22db1722021-06-09 10:53:51 -0700498 auto raw = const_cast<typename T::value_type*>(value.data());
499 explicit_bzero(raw, value.size() * sizeof(*raw));
500}
501
502class Credentials
503{
504 public:
505 Credentials(std::string&& user, std::string&& password) :
506 userBuf(std::move(user)), passBuf(std::move(password))
507 {}
508
509 ~Credentials()
510 {
511 secureCleanup(userBuf);
512 secureCleanup(passBuf);
513 }
514
515 const std::string& user()
516 {
517 return userBuf;
518 }
519
520 const std::string& password()
521 {
522 return passBuf;
523 }
524
525 Credentials() = delete;
526 Credentials(const Credentials&) = delete;
527 Credentials& operator=(const Credentials&) = delete;
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800528 Credentials(Credentials&&) = delete;
529 Credentials& operator=(Credentials&&) = delete;
Ed Tanous22db1722021-06-09 10:53:51 -0700530
531 private:
532 std::string userBuf;
533 std::string passBuf;
534};
535
536class CredentialsProvider
537{
538 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500539 template <typename T>
Ed Tanous22db1722021-06-09 10:53:51 -0700540 struct Deleter
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100541 {
Ed Tanous22db1722021-06-09 10:53:51 -0700542 void operator()(T* buff) const
543 {
544 if (buff)
545 {
546 secureCleanup(*buff);
547 delete buff;
548 }
549 }
550 };
551
552 using Buffer = std::vector<char>;
553 using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
554 // Using explicit definition instead of std::function to avoid implicit
555 // conversions eg. stack copy instead of reference
556 using FormatterFunc = void(const std::string& username,
557 const std::string& password, Buffer& dest);
558
559 CredentialsProvider(std::string&& user, std::string&& password) :
560 credentials(std::move(user), std::move(password))
561 {}
562
563 const std::string& user()
564 {
565 return credentials.user();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100566 }
567
Ed Tanous22db1722021-06-09 10:53:51 -0700568 const std::string& password()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100569 {
Ed Tanous22db1722021-06-09 10:53:51 -0700570 return credentials.password();
571 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100572
Ed Tanous1917ee92022-06-30 22:30:50 -0700573 SecureBuffer pack(FormatterFunc* formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100574 {
Ed Tanous22db1722021-06-09 10:53:51 -0700575 SecureBuffer packed{new Buffer{}};
Ed Tanouse662eae2022-01-25 10:39:19 -0800576 if (formatter != nullptr)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100577 {
Ed Tanous22db1722021-06-09 10:53:51 -0700578 formatter(credentials.user(), credentials.password(), *packed);
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100579 }
580
Ed Tanous22db1722021-06-09 10:53:51 -0700581 return packed;
582 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100583
Ed Tanous22db1722021-06-09 10:53:51 -0700584 private:
585 Credentials credentials;
586};
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100587
Ed Tanous22db1722021-06-09 10:53:51 -0700588// Wrapper for boost::async_pipe ensuring proper pipe cleanup
589template <typename Buffer>
590class Pipe
591{
592 public:
593 using unix_fd = sdbusplus::message::unix_fd;
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100594
Ed Tanous8a592812022-06-04 09:06:59 -0700595 Pipe(boost::asio::io_context& io, Buffer&& bufferIn) :
596 impl(io), buffer{std::move(bufferIn)}
Ed Tanous22db1722021-06-09 10:53:51 -0700597 {}
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100598
Ed Tanous22db1722021-06-09 10:53:51 -0700599 ~Pipe()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100600 {
Ed Tanous22db1722021-06-09 10:53:51 -0700601 // Named pipe needs to be explicitly removed
602 impl.close();
603 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100604
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800605 Pipe(const Pipe&) = delete;
606 Pipe(Pipe&&) = delete;
607 Pipe& operator=(const Pipe&) = delete;
608 Pipe& operator=(Pipe&&) = delete;
609
Ed Tanous22db1722021-06-09 10:53:51 -0700610 unix_fd fd()
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200611 {
Ed Tanous22db1722021-06-09 10:53:51 -0700612 return unix_fd{impl.native_source()};
613 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100614
Ed Tanous22db1722021-06-09 10:53:51 -0700615 template <typename WriteHandler>
616 void asyncWrite(WriteHandler&& handler)
617 {
618 impl.async_write_some(data(), std::forward<WriteHandler>(handler));
619 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100620
Ed Tanous22db1722021-06-09 10:53:51 -0700621 private:
622 // Specialization for pointer types
623 template <typename B = Buffer>
624 typename std::enable_if<boost::has_dereference<B>::value,
625 boost::asio::const_buffer>::type
626 data()
627 {
628 return boost::asio::buffer(*buffer);
629 }
630
631 template <typename B = Buffer>
632 typename std::enable_if<!boost::has_dereference<B>::value,
633 boost::asio::const_buffer>::type
634 data()
635 {
636 return boost::asio::buffer(buffer);
637 }
638
639 const std::string name;
640 boost::process::async_pipe impl;
641 Buffer buffer;
642};
643
644/**
645 * @brief Function transceives data with dbus directly.
646 *
647 * All BMC state properties will be retrieved before sending reset request.
648 */
649inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
650 const std::string& service, const std::string& name,
651 const std::string& imageUrl, const bool rw,
652 std::string&& userName, std::string&& password)
653{
654 using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
655 constexpr const size_t secretLimit = 1024;
656
657 std::shared_ptr<SecurePipe> secretPipe;
Ed Tanous168e20c2021-12-13 14:39:53 -0800658 dbus::utility::DbusVariantType unixFd = -1;
Ed Tanous22db1722021-06-09 10:53:51 -0700659
660 if (!userName.empty() || !password.empty())
661 {
662 // Encapsulate in safe buffer
663 CredentialsProvider credentials(std::move(userName),
664 std::move(password));
665
666 // Payload must contain data + NULL delimiters
667 if (credentials.user().size() + credentials.password().size() + 2 >
668 secretLimit)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100669 {
Ed Tanous22db1722021-06-09 10:53:51 -0700670 BMCWEB_LOG_ERROR << "Credentials too long to handle";
671 messages::unrecognizedRequestBody(asyncResp->res);
672 return;
673 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100674
Ed Tanous22db1722021-06-09 10:53:51 -0700675 // Pack secret
676 auto secret = credentials.pack(
677 [](const auto& user, const auto& pass, auto& buff) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700678 std::copy(user.begin(), user.end(), std::back_inserter(buff));
679 buff.push_back('\0');
680 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
681 buff.push_back('\0');
682 });
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100683
Ed Tanous22db1722021-06-09 10:53:51 -0700684 // Open pipe
685 secretPipe = std::make_shared<SecurePipe>(
686 crow::connections::systemBus->get_io_context(), std::move(secret));
687 unixFd = secretPipe->fd();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100688
Ed Tanous22db1722021-06-09 10:53:51 -0700689 // Pass secret over pipe
690 secretPipe->asyncWrite(
691 [asyncResp](const boost::system::error_code& ec, std::size_t) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700692 if (ec)
693 {
694 BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
695 messages::internalError(asyncResp->res);
696 }
697 });
Ed Tanous22db1722021-06-09 10:53:51 -0700698 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100699
Ed Tanous22db1722021-06-09 10:53:51 -0700700 crow::connections::systemBus->async_method_call(
701 [asyncResp, secretPipe](const boost::system::error_code ec,
702 bool success) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700703 if (ec)
704 {
705 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
706 messages::internalError(asyncResp->res);
707 }
708 else if (!success)
709 {
710 BMCWEB_LOG_ERROR << "Service responded with error";
711 messages::generalError(asyncResp->res);
712 }
Ed Tanous22db1722021-06-09 10:53:51 -0700713 },
714 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
715 "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
716 unixFd);
717}
718
719/**
720 * @brief Function transceives data with dbus directly.
721 *
722 * All BMC state properties will be retrieved before sending reset request.
723 */
724inline void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
725 const std::string& service, const std::string& name,
726 bool legacy)
727{
728
729 // Legacy mount requires parameter with image
730 if (legacy)
731 {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100732 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700733 [asyncResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700734 if (ec)
735 {
736 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700737
Ed Tanous002d39b2022-05-31 08:59:27 -0700738 messages::internalError(asyncResp->res);
739 return;
740 }
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100741 },
742 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
Ed Tanous22db1722021-06-09 10:53:51 -0700743 "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200744 }
Ed Tanous22db1722021-06-09 10:53:51 -0700745 else // proxy
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200746 {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200747 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700748 [asyncResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700749 if (ec)
750 {
751 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700752
Ed Tanous002d39b2022-05-31 08:59:27 -0700753 messages::internalError(asyncResp->res);
754 return;
755 }
Ed Tanous22db1722021-06-09 10:53:51 -0700756 },
757 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
758 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
759 }
760}
761
Ed Tanous96825be2022-06-03 09:43:38 -0700762inline void handleManagersVirtualMediaActionInsertPost(
763 crow::App& app, const crow::Request& req,
764 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
765 const std::string& name, const std::string& resName)
766{
767 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
768 {
769 return;
770 }
771 if (name != "bmc")
772 {
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200773 messages::resourceNotFound(asyncResp->res, "VirtualMedia.InsertMedia",
Ed Tanous96825be2022-06-03 09:43:38 -0700774 resName);
775
776 return;
777 }
778 InsertMediaActionParams actionParams;
779
780 // Read obligatory parameters (url of
781 // image)
782 if (!json_util::readJsonAction(
783 req, asyncResp->res, "Image", actionParams.imageUrl,
784 "WriteProtected", actionParams.writeProtected, "UserName",
785 actionParams.userName, "Password", actionParams.password,
786 "Inserted", actionParams.inserted, "TransferMethod",
787 actionParams.transferMethod, "TransferProtocolType",
788 actionParams.transferProtocolType))
789 {
790 BMCWEB_LOG_DEBUG << "Image is not provided";
791 return;
792 }
793
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200794 bool paramsValid = validateParams(asyncResp->res, actionParams);
Ed Tanous96825be2022-06-03 09:43:38 -0700795 if (!paramsValid)
796 {
797 return;
798 }
799
800 crow::connections::systemBus->async_method_call(
801 [asyncResp, actionParams,
802 resName](const boost::system::error_code ec,
803 const dbus::utility::MapperGetObject& getObjectType) mutable {
804 if (ec)
805 {
806 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
807 messages::internalError(asyncResp->res);
808
809 return;
810 }
811 std::string service = getObjectType.begin()->first;
812 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
813
814 crow::connections::systemBus->async_method_call(
815 [service, resName, actionParams,
Ed Tanous8a592812022-06-04 09:06:59 -0700816 asyncResp](const boost::system::error_code ec2,
Ed Tanous96825be2022-06-03 09:43:38 -0700817 dbus::utility::ManagedObjectType& subtree) mutable {
Ed Tanous8a592812022-06-04 09:06:59 -0700818 if (ec2)
Ed Tanous96825be2022-06-03 09:43:38 -0700819 {
820 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200821 messages::internalError(asyncResp->res);
Ed Tanous96825be2022-06-03 09:43:38 -0700822
823 return;
824 }
825
826 for (const auto& object : subtree)
827 {
828 const std::string& path =
829 static_cast<const std::string&>(object.first);
830
831 std::size_t lastIndex = path.rfind('/');
832 if (lastIndex == std::string::npos)
833 {
834 continue;
835 }
836
837 lastIndex += 1;
838
839 if (path.substr(lastIndex) == resName)
840 {
841 lastIndex = path.rfind("Proxy");
842 if (lastIndex != std::string::npos)
843 {
844 // Not possible in proxy mode
845 BMCWEB_LOG_DEBUG << "InsertMedia not "
846 "allowed in proxy mode";
847 messages::resourceNotFound(asyncResp->res,
848 "VirtualMedia.InsertMedia",
849 resName);
850
851 return;
852 }
853
854 lastIndex = path.rfind("Legacy");
855 if (lastIndex == std::string::npos)
856 {
857 continue;
858 }
859
860 // manager is irrelevant for
861 // VirtualMedia dbus calls
862 doMountVmLegacy(asyncResp, service, resName,
863 actionParams.imageUrl,
864 !(*actionParams.writeProtected),
865 std::move(*actionParams.userName),
866 std::move(*actionParams.password));
867
868 return;
869 }
870 }
871 BMCWEB_LOG_DEBUG << "Parent item not found";
872 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
873 },
874 service, "/xyz/openbmc_project/VirtualMedia",
875 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
876 },
877 "xyz.openbmc_project.ObjectMapper",
878 "/xyz/openbmc_project/object_mapper",
879 "xyz.openbmc_project.ObjectMapper", "GetObject",
880 "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>());
881}
882
883inline void handleManagersVirtualMediaActionEject(
884 crow::App& app, const crow::Request& req,
885 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
886 const std::string& managerName, const std::string& resName)
887{
888 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
889 {
890 return;
891 }
892 if (managerName != "bmc")
893 {
894 messages::resourceNotFound(asyncResp->res, "VirtualMedia.Eject",
895 resName);
896
897 return;
898 }
899
900 crow::connections::systemBus->async_method_call(
901 [asyncResp,
Ed Tanous8a592812022-06-04 09:06:59 -0700902 resName](const boost::system::error_code ec2,
Ed Tanous96825be2022-06-03 09:43:38 -0700903 const dbus::utility::MapperGetObject& getObjectType) {
Ed Tanous8a592812022-06-04 09:06:59 -0700904 if (ec2)
Ed Tanous96825be2022-06-03 09:43:38 -0700905 {
Ed Tanous8a592812022-06-04 09:06:59 -0700906 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec2;
Ed Tanous96825be2022-06-03 09:43:38 -0700907 messages::internalError(asyncResp->res);
908
909 return;
910 }
911 std::string service = getObjectType.begin()->first;
912 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
913
914 crow::connections::systemBus->async_method_call(
Ed Tanous02cad962022-06-30 16:50:15 -0700915 [resName, service, asyncResp{asyncResp}](
916 const boost::system::error_code ec,
917 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous96825be2022-06-03 09:43:38 -0700918 if (ec)
919 {
920 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200921 messages::internalError(asyncResp->res);
Ed Tanous96825be2022-06-03 09:43:38 -0700922
923 return;
924 }
925
926 for (const auto& object : subtree)
927 {
928 const std::string& path =
929 static_cast<const std::string&>(object.first);
930
931 std::size_t lastIndex = path.rfind('/');
932 if (lastIndex == std::string::npos)
933 {
934 continue;
935 }
936
937 lastIndex += 1;
938
939 if (path.substr(lastIndex) == resName)
940 {
941 lastIndex = path.rfind("Proxy");
942 if (lastIndex != std::string::npos)
943 {
944 // Proxy mode
945 doVmAction(asyncResp, service, resName, false);
946 }
947
948 lastIndex = path.rfind("Legacy");
949 if (lastIndex != std::string::npos)
950 {
951 // Legacy mode
952 doVmAction(asyncResp, service, resName, true);
953 }
954
955 return;
956 }
957 }
958 BMCWEB_LOG_DEBUG << "Parent item not found";
959 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
960 },
961 service, "/xyz/openbmc_project/VirtualMedia",
962 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
963 },
964 "xyz.openbmc_project.ObjectMapper",
965 "/xyz/openbmc_project/object_mapper",
966 "xyz.openbmc_project.ObjectMapper", "GetObject",
967 "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>());
968}
969
970inline void handleManagersVirtualMediaCollectionGet(
971 crow::App& app, const crow::Request& req,
972 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
973 const std::string& name)
974{
975 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
976 {
977 return;
978 }
979 if (name != "bmc")
980 {
981 messages::resourceNotFound(asyncResp->res, "VirtualMedia", name);
982
983 return;
984 }
985
986 asyncResp->res.jsonValue["@odata.type"] =
987 "#VirtualMediaCollection.VirtualMediaCollection";
988 asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
Ed Tanousfdb20342022-06-03 09:56:52 -0700989 asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
990 "redfish", "v1", "Managers", name, "VirtualMedia");
Ed Tanous96825be2022-06-03 09:43:38 -0700991
992 crow::connections::systemBus->async_method_call(
993 [asyncResp, name](const boost::system::error_code ec,
994 const dbus::utility::MapperGetObject& getObjectType) {
995 if (ec)
996 {
997 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
998 messages::internalError(asyncResp->res);
999
1000 return;
1001 }
1002 std::string service = getObjectType.begin()->first;
1003 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1004
1005 getVmResourceList(asyncResp, service, name);
1006 },
1007 "xyz.openbmc_project.ObjectMapper",
1008 "/xyz/openbmc_project/object_mapper",
1009 "xyz.openbmc_project.ObjectMapper", "GetObject",
1010 "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>());
1011}
1012
1013inline void
1014 handleVirtualMediaGet(crow::App& app, const crow::Request& req,
1015 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1016 const std::string& name, const std::string& resName)
1017{
1018 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1019 {
1020 return;
1021 }
1022 if (name != "bmc")
1023 {
1024 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
1025
1026 return;
1027 }
1028
1029 crow::connections::systemBus->async_method_call(
1030 [asyncResp, name,
1031 resName](const boost::system::error_code ec,
1032 const dbus::utility::MapperGetObject& getObjectType) {
1033 if (ec)
1034 {
1035 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
1036 messages::internalError(asyncResp->res);
1037
1038 return;
1039 }
1040 std::string service = getObjectType.begin()->first;
1041 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1042
1043 getVmData(asyncResp, service, name, resName);
1044 },
1045 "xyz.openbmc_project.ObjectMapper",
1046 "/xyz/openbmc_project/object_mapper",
1047 "xyz.openbmc_project.ObjectMapper", "GetObject",
1048 "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>());
1049}
1050
Ed Tanous22db1722021-06-09 10:53:51 -07001051inline void requestNBDVirtualMediaRoutes(App& app)
1052{
George Liu0fda0f12021-11-16 10:06:17 +08001053 BMCWEB_ROUTE(
1054 app,
1055 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
Ed Tanoused398212021-06-09 17:05:54 -07001056 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous96825be2022-06-03 09:43:38 -07001057 .methods(boost::beast::http::verb::post)(std::bind_front(
1058 handleManagersVirtualMediaActionInsertPost, std::ref(app)));
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +02001059
George Liu0fda0f12021-11-16 10:06:17 +08001060 BMCWEB_ROUTE(
1061 app,
1062 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
Ed Tanoused398212021-06-09 17:05:54 -07001063 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous96825be2022-06-03 09:43:38 -07001064 .methods(boost::beast::http::verb::post)(std::bind_front(
1065 handleManagersVirtualMediaActionEject, std::ref(app)));
Ed Tanous002d39b2022-05-31 08:59:27 -07001066
Ed Tanous22db1722021-06-09 10:53:51 -07001067 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
Ed Tanoused398212021-06-09 17:05:54 -07001068 .privileges(redfish::privileges::getVirtualMediaCollection)
Ed Tanous96825be2022-06-03 09:43:38 -07001069 .methods(boost::beast::http::verb::get)(std::bind_front(
1070 handleManagersVirtualMediaCollectionGet, std::ref(app)));
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001071
Ed Tanous22db1722021-06-09 10:53:51 -07001072 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001073 .privileges(redfish::privileges::getVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -07001074 .methods(boost::beast::http::verb::get)(
Ed Tanous96825be2022-06-03 09:43:38 -07001075 std::bind_front(handleVirtualMediaGet, std::ref(app)));
Ed Tanous22db1722021-06-09 10:53:51 -07001076}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001077
1078} // namespace redfish