blob: ed027a7a7f195345b0d39106a70d745fd4e8286c [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 Tanousb9d36b42022-02-26 21:42:46 -080018#include <account_service.hpp>
John Edward Broadbent7e860f12021-04-08 15:57:16 -070019#include <app.hpp>
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +010020#include <boost/process/async_pipe.hpp>
21#include <boost/type_traits/has_dereference.hpp>
Anna Platash9e319cf2020-11-17 10:18:31 +010022#include <boost/url/url_view.hpp>
Ed Tanous45ca1b82022-03-25 13:07:27 -070023#include <query.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070024#include <registries/privilege_registry.hpp>
Ed Tanousb9d36b42022-02-26 21:42:46 -080025#include <utils/json_utils.hpp>
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020026
27namespace redfish
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020028{
Anna Platash9e319cf2020-11-17 10:18:31 +010029/**
30 * @brief Function extracts transfer protocol name from URI.
31 */
Ed Tanous67df0732021-10-26 11:23:56 -070032inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
33{
34 boost::urls::result<boost::urls::url_view> url =
Ed Tanous079360a2022-06-29 10:05:19 -070035 boost::urls::parse_uri(imageUri);
Ed Tanous67df0732021-10-26 11:23:56 -070036 if (!url)
37 {
38 return "None";
39 }
Ed Tanous079360a2022-06-29 10:05:19 -070040 std::string_view scheme = url->scheme();
Ed Tanous67df0732021-10-26 11:23:56 -070041 if (scheme == "smb")
42 {
43 return "CIFS";
44 }
45 if (scheme == "https")
46 {
47 return "HTTPS";
48 }
49
50 return "None";
51}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020052
53/**
54 * @brief Read all known properties from VM object interfaces
55 */
Ed Tanous22db1722021-06-09 10:53:51 -070056inline void
Ed Tanous8a592812022-06-04 09:06:59 -070057 vmParseInterfaceObject(const dbus::utility::DBusInteracesMap& interfaces,
zhanghch058d1b46d2021-04-01 11:18:24 +080058 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020059{
Ed Tanous8a592812022-06-04 09:06:59 -070060 for (const auto& [interface, values] : interfaces)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020061 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080062 if (interface == "xyz.openbmc_project.VirtualMedia.MountPoint")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020063 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080064 for (const auto& [property, value] : values)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020065 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080066 if (property == "EndpointId")
67 {
68 const std::string* endpointIdValue =
69 std::get_if<std::string>(&value);
70 if (endpointIdValue == nullptr)
71 {
72 continue;
73 }
74 if (!endpointIdValue->empty())
75 {
76 // Proxy mode
77 aResp->res
78 .jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
79 *endpointIdValue;
80 aResp->res.jsonValue["TransferProtocolType"] = "OEM";
81 }
82 }
83 if (property == "ImageURL")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020084 {
Anna Platash9e319cf2020-11-17 10:18:31 +010085 const std::string* imageUrlValue =
Ed Tanous711ac7a2021-12-20 09:34:41 -080086 std::get_if<std::string>(&value);
Ed Tanous26f69762022-01-25 09:49:11 -080087 if (imageUrlValue != nullptr && !imageUrlValue->empty())
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +010088 {
Anna Platash9e319cf2020-11-17 10:18:31 +010089 std::filesystem::path filePath = *imageUrlValue;
90 if (!filePath.has_filename())
91 {
92 // this will handle https share, which not
93 // necessarily has to have filename given.
94 aResp->res.jsonValue["ImageName"] = "";
95 }
96 else
97 {
98 aResp->res.jsonValue["ImageName"] =
99 filePath.filename();
100 }
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100101
Anna Platash9e319cf2020-11-17 10:18:31 +0100102 aResp->res.jsonValue["Image"] = *imageUrlValue;
Anna Platash9e319cf2020-11-17 10:18:31 +0100103 aResp->res.jsonValue["TransferProtocolType"] =
104 getTransferProtocolTypeFromUri(*imageUrlValue);
105
Ed Tanous711ac7a2021-12-20 09:34:41 -0800106 aResp->res.jsonValue["ConnectedVia"] = "URI";
Anna Platash9e319cf2020-11-17 10:18:31 +0100107 }
108 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800109 if (property == "WriteProtected")
Anna Platash9e319cf2020-11-17 10:18:31 +0100110 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800111 const bool* writeProtectedValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800112 if (writeProtectedValue != nullptr)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200113 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100114 aResp->res.jsonValue["WriteProtected"] =
115 *writeProtectedValue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200116 }
117 }
118 }
119 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800120 if (interface == "xyz.openbmc_project.VirtualMedia.Process")
121 {
122 for (const auto& [property, value] : values)
123 {
124 if (property == "Active")
125 {
126 const bool* activeValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800127 if (activeValue == nullptr)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800128 {
129 BMCWEB_LOG_DEBUG << "Value Active not found";
130 return;
131 }
132 aResp->res.jsonValue["Inserted"] = *activeValue;
133
Ed Tanouse05aec52022-01-25 10:28:56 -0800134 if (*activeValue)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800135 {
136 aResp->res.jsonValue["ConnectedVia"] = "Applet";
137 }
138 }
139 }
140 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200141 }
142}
143
144/**
145 * @brief Fill template for Virtual Media Item.
146 */
Ed Tanous22db1722021-06-09 10:53:51 -0700147inline nlohmann::json vmItemTemplate(const std::string& name,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500148 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200149{
150 nlohmann::json item;
Ed Tanousfdb20342022-06-03 09:56:52 -0700151 item["@odata.id"] = crow::utility::urlFromPieces(
152 "redfish", "v1", "Managers", name, "VirtualMedia", resName);
Ed Tanous22db1722021-06-09 10:53:51 -0700153
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100154 item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200155 item["Name"] = "Virtual Removable Media";
156 item["Id"] = resName;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200157 item["WriteProtected"] = true;
Ed Tanous613dabe2022-07-09 11:17:36 -0700158 item["MediaTypes"] = nlohmann::json::array_t({"CD", "USBStick"});
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200159 item["TransferMethod"] = "Stream";
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100160 item["Oem"]["OpenBMC"]["@odata.type"] =
161 "#OemVirtualMedia.v1_0_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200162
163 return item;
164}
165
166/**
167 * @brief Fills collection data
168 */
Ed Tanous22db1722021-06-09 10:53:51 -0700169inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500170 const std::string& service,
171 const std::string& name)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200172{
173 BMCWEB_LOG_DEBUG << "Get available Virtual Media resources.";
174 crow::connections::systemBus->async_method_call(
Ed Tanous02cad962022-06-30 16:50:15 -0700175 [name, aResp{std::move(aResp)}](
176 const boost::system::error_code ec,
177 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700178 if (ec)
179 {
180 BMCWEB_LOG_DEBUG << "DBUS response error";
181 return;
182 }
183 nlohmann::json& members = aResp->res.jsonValue["Members"];
184 members = nlohmann::json::array();
185
186 for (const auto& object : subtree)
187 {
188 nlohmann::json item;
189 std::string path = object.first.filename();
190 if (path.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200191 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700192 continue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200193 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200194
Ed Tanousfdb20342022-06-03 09:56:52 -0700195 item["@odata.id"] = crow::utility::urlFromPieces(
196 "redfish", "v1", "Managers", name, "VirtualMedia", path);
Ed Tanous002d39b2022-05-31 08:59:27 -0700197 members.emplace_back(std::move(item));
198 }
199 aResp->res.jsonValue["Members@odata.count"] = members.size();
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200200 },
201 service, "/xyz/openbmc_project/VirtualMedia",
202 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
203}
204
205/**
206 * @brief Fills data for specific resource
207 */
Ed Tanous22db1722021-06-09 10:53:51 -0700208inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500209 const std::string& service, const std::string& name,
210 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200211{
212 BMCWEB_LOG_DEBUG << "Get Virtual Media resource data.";
213
214 crow::connections::systemBus->async_method_call(
Ed Tanous914e2d52022-01-07 11:38:34 -0800215 [resName, name,
216 aResp](const boost::system::error_code ec,
217 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700218 if (ec)
219 {
220 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200221
Ed Tanous002d39b2022-05-31 08:59:27 -0700222 return;
223 }
224
225 for (const auto& item : subtree)
226 {
227 std::string thispath = item.first.filename();
228 if (thispath.empty())
229 {
230 continue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200231 }
232
Ed Tanous002d39b2022-05-31 08:59:27 -0700233 if (thispath != resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200234 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700235 continue;
236 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200237
Ed Tanous002d39b2022-05-31 08:59:27 -0700238 // "Legacy"/"Proxy"
239 auto mode = item.first.parent_path();
240 // "VirtualMedia"
241 auto type = mode.parent_path();
242 if (mode.filename().empty() || type.filename().empty())
243 {
244 continue;
245 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200246
Ed Tanous002d39b2022-05-31 08:59:27 -0700247 if (type.filename() != "VirtualMedia")
248 {
249 continue;
250 }
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200251
Ed Tanous002d39b2022-05-31 08:59:27 -0700252 aResp->res.jsonValue = vmItemTemplate(name, resName);
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200253
Ed Tanous002d39b2022-05-31 08:59:27 -0700254 // Check if dbus path is Legacy type
255 if (mode.filename() == "Legacy")
256 {
257 aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
Ed Tanousfdb20342022-06-03 09:56:52 -0700258 ["target"] = crow::utility::urlFromPieces(
259 "redfish", "v1", "Managers", name, "VirtualMedia", resName,
260 "Actions", "VirtualMedia.InsertMedia");
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200261 }
262
Ed Tanous002d39b2022-05-31 08:59:27 -0700263 vmParseInterfaceObject(item.second, aResp);
264
265 aResp->res
266 .jsonValue["Actions"]["#VirtualMedia.EjectMedia"]["target"] =
Ed Tanousfdb20342022-06-03 09:56:52 -0700267 crow::utility::urlFromPieces("redfish", "v1", "Managers", name,
268 "VirtualMedia", resName, "Actions",
269 "VirtualMedia.EjectMedia");
Ed Tanous002d39b2022-05-31 08:59:27 -0700270 return;
271 }
272
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +0800273 messages::resourceNotFound(aResp->res, "VirtualMedia", resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200274 },
275 service, "/xyz/openbmc_project/VirtualMedia",
276 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
277}
278
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200279/**
Ed Tanous22db1722021-06-09 10:53:51 -0700280 * @brief Transfer protocols supported for InsertMedia action.
281 *
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200282 */
Ed Tanous22db1722021-06-09 10:53:51 -0700283enum class TransferProtocol
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200284{
Ed Tanous22db1722021-06-09 10:53:51 -0700285 https,
286 smb,
287 invalid
288};
289
290/**
291 * @brief Function extracts transfer protocol type from URI.
292 *
293 */
Ed Tanous67df0732021-10-26 11:23:56 -0700294inline std::optional<TransferProtocol>
Ed Tanousace85d62021-10-26 12:45:59 -0700295 getTransferProtocolFromUri(const boost::urls::url_view& imageUri)
Ed Tanous67df0732021-10-26 11:23:56 -0700296{
Ed Tanous079360a2022-06-29 10:05:19 -0700297 std::string_view scheme = imageUri.scheme();
Ed Tanous67df0732021-10-26 11:23:56 -0700298 if (scheme == "smb")
299 {
300 return TransferProtocol::smb;
301 }
302 if (scheme == "https")
303 {
304 return TransferProtocol::https;
305 }
306 if (!scheme.empty())
307 {
308 return TransferProtocol::invalid;
309 }
310
311 return {};
312}
Ed Tanous22db1722021-06-09 10:53:51 -0700313
314/**
315 * @brief Function convert transfer protocol from string param.
316 *
317 */
318inline std::optional<TransferProtocol> getTransferProtocolFromParam(
319 const std::optional<std::string>& transferProtocolType)
320{
321 if (transferProtocolType == std::nullopt)
Agata Olenderc6f4e012020-03-11 15:19:07 +0100322 {
Ed Tanous22db1722021-06-09 10:53:51 -0700323 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100324 }
325
Ed Tanous22db1722021-06-09 10:53:51 -0700326 if (*transferProtocolType == "CIFS")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200327 {
Ed Tanous22db1722021-06-09 10:53:51 -0700328 return TransferProtocol::smb;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200329 }
330
Ed Tanous22db1722021-06-09 10:53:51 -0700331 if (*transferProtocolType == "HTTPS")
332 {
333 return TransferProtocol::https;
334 }
335
336 return TransferProtocol::invalid;
337}
338
339/**
340 * @brief Function extends URI with transfer protocol type.
341 *
342 */
343inline std::string
344 getUriWithTransferProtocol(const std::string& imageUri,
345 const TransferProtocol& transferProtocol)
346{
347 if (transferProtocol == TransferProtocol::smb)
348 {
349 return "smb://" + imageUri;
350 }
351
352 if (transferProtocol == TransferProtocol::https)
353 {
354 return "https://" + imageUri;
355 }
356
357 return imageUri;
358}
359
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200360struct InsertMediaActionParams
361{
362 std::string imageUrl;
363 std::optional<std::string> userName;
364 std::optional<std::string> password;
365 std::optional<std::string> transferMethod;
366 std::optional<std::string> transferProtocolType;
367 std::optional<bool> writeProtected = true;
368 std::optional<bool> inserted;
369};
370
Ed Tanous22db1722021-06-09 10:53:51 -0700371/**
372 * @brief Function validate parameters of insert media request.
373 *
374 */
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200375inline bool validateParams(crow::Response& res,
376 InsertMediaActionParams& actionParams)
Ed Tanous22db1722021-06-09 10:53:51 -0700377{
378 BMCWEB_LOG_DEBUG << "Validation started";
379 // required param imageUrl must not be empty
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200380 if (actionParams.imageUrl.empty())
Ed Tanous22db1722021-06-09 10:53:51 -0700381 {
382 BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
383
384 messages::propertyValueFormatError(res, "<empty>", "Image");
385
386 return false;
387 }
388
389 // optional param inserted must be true
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200390 if ((actionParams.inserted != std::nullopt) && !*actionParams.inserted)
Ed Tanous22db1722021-06-09 10:53:51 -0700391 {
392 BMCWEB_LOG_ERROR
393 << "Request action optional parameter Inserted must be true.";
394
395 messages::actionParameterNotSupported(res, "Inserted", "InsertMedia");
396
397 return false;
398 }
399
400 // optional param transferMethod must be stream
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200401 if ((actionParams.transferMethod != std::nullopt) &&
402 (*actionParams.transferMethod != "Stream"))
Ed Tanous22db1722021-06-09 10:53:51 -0700403 {
404 BMCWEB_LOG_ERROR << "Request action optional parameter "
405 "TransferMethod must be Stream.";
406
407 messages::actionParameterNotSupported(res, "TransferMethod",
408 "InsertMedia");
409
410 return false;
411 }
Ed Tanousace85d62021-10-26 12:45:59 -0700412 boost::urls::result<boost::urls::url_view> url =
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200413 boost::urls::parse_uri(boost::string_view(actionParams.imageUrl));
Ed Tanousace85d62021-10-26 12:45:59 -0700414 if (!url)
415 {
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200416 messages::actionParameterValueFormatError(res, actionParams.imageUrl,
417 "Image", "InsertMedia");
Michal Orzel9bc55692022-06-14 15:50:50 +0200418 return false;
Ed Tanousace85d62021-10-26 12:45:59 -0700419 }
Ed Tanous22db1722021-06-09 10:53:51 -0700420 std::optional<TransferProtocol> uriTransferProtocolType =
Ed Tanousace85d62021-10-26 12:45:59 -0700421 getTransferProtocolFromUri(*url);
Ed Tanous22db1722021-06-09 10:53:51 -0700422
423 std::optional<TransferProtocol> paramTransferProtocolType =
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200424 getTransferProtocolFromParam(actionParams.transferProtocolType);
Ed Tanous22db1722021-06-09 10:53:51 -0700425
426 // ImageUrl does not contain valid protocol type
427 if (*uriTransferProtocolType == TransferProtocol::invalid)
428 {
429 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
430 "contain specified protocol type from list: "
431 "(smb, https).";
432
Ed Tanousace85d62021-10-26 12:45:59 -0700433 messages::resourceAtUriInUnknownFormat(res, *url);
Ed Tanous22db1722021-06-09 10:53:51 -0700434
435 return false;
436 }
437
438 // transferProtocolType should contain value from list
439 if (*paramTransferProtocolType == TransferProtocol::invalid)
440 {
441 BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
442 "must be provided with value from list: "
443 "(CIFS, HTTPS).";
444
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200445 messages::propertyValueNotInList(
446 res, *actionParams.transferProtocolType, "TransferProtocolType");
Ed Tanous22db1722021-06-09 10:53:51 -0700447 return false;
448 }
449
450 // valid transfer protocol not provided either with URI nor param
451 if ((uriTransferProtocolType == std::nullopt) &&
452 (paramTransferProtocolType == std::nullopt))
453 {
454 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
455 "contain specified protocol type or param "
456 "TransferProtocolType must be provided.";
457
Ed Tanousace85d62021-10-26 12:45:59 -0700458 messages::resourceAtUriInUnknownFormat(res, *url);
Ed Tanous22db1722021-06-09 10:53:51 -0700459
460 return false;
461 }
462
463 // valid transfer protocol provided both with URI and param
464 if ((paramTransferProtocolType != std::nullopt) &&
465 (uriTransferProtocolType != std::nullopt))
466 {
467 // check if protocol is the same for URI and param
468 if (*paramTransferProtocolType != *uriTransferProtocolType)
469 {
470 BMCWEB_LOG_ERROR << "Request action parameter "
471 "TransferProtocolType must contain the "
472 "same protocol type as protocol type "
473 "provided with param imageUrl.";
474
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200475 messages::actionParameterValueTypeError(
476 res, *actionParams.transferProtocolType, "TransferProtocolType",
477 "InsertMedia");
Ed Tanous22db1722021-06-09 10:53:51 -0700478
479 return false;
480 }
481 }
482
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200483 // validation passed, add protocol to URI if needed
Ed Tanous22db1722021-06-09 10:53:51 -0700484 if (uriTransferProtocolType == std::nullopt)
485 {
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200486 actionParams.imageUrl = getUriWithTransferProtocol(
487 actionParams.imageUrl, *paramTransferProtocolType);
Ed Tanous22db1722021-06-09 10:53:51 -0700488 }
489
490 return true;
491}
492
493template <typename T>
494static void secureCleanup(T& value)
495{
Ed Tanous4ecc6182022-01-07 09:36:26 -0800496 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
Ed Tanous22db1722021-06-09 10:53:51 -0700497 auto raw = const_cast<typename T::value_type*>(value.data());
498 explicit_bzero(raw, value.size() * sizeof(*raw));
499}
500
501class Credentials
502{
503 public:
504 Credentials(std::string&& user, std::string&& password) :
505 userBuf(std::move(user)), passBuf(std::move(password))
506 {}
507
508 ~Credentials()
509 {
510 secureCleanup(userBuf);
511 secureCleanup(passBuf);
512 }
513
514 const std::string& user()
515 {
516 return userBuf;
517 }
518
519 const std::string& password()
520 {
521 return passBuf;
522 }
523
524 Credentials() = delete;
525 Credentials(const Credentials&) = delete;
526 Credentials& operator=(const Credentials&) = delete;
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800527 Credentials(Credentials&&) = delete;
528 Credentials& operator=(Credentials&&) = delete;
Ed Tanous22db1722021-06-09 10:53:51 -0700529
530 private:
531 std::string userBuf;
532 std::string passBuf;
533};
534
535class CredentialsProvider
536{
537 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500538 template <typename T>
Ed Tanous22db1722021-06-09 10:53:51 -0700539 struct Deleter
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100540 {
Ed Tanous22db1722021-06-09 10:53:51 -0700541 void operator()(T* buff) const
542 {
543 if (buff)
544 {
545 secureCleanup(*buff);
546 delete buff;
547 }
548 }
549 };
550
551 using Buffer = std::vector<char>;
552 using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
553 // Using explicit definition instead of std::function to avoid implicit
554 // conversions eg. stack copy instead of reference
555 using FormatterFunc = void(const std::string& username,
556 const std::string& password, Buffer& dest);
557
558 CredentialsProvider(std::string&& user, std::string&& password) :
559 credentials(std::move(user), std::move(password))
560 {}
561
562 const std::string& user()
563 {
564 return credentials.user();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100565 }
566
Ed Tanous22db1722021-06-09 10:53:51 -0700567 const std::string& password()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100568 {
Ed Tanous22db1722021-06-09 10:53:51 -0700569 return credentials.password();
570 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100571
Ed Tanous1917ee92022-06-30 22:30:50 -0700572 SecureBuffer pack(FormatterFunc* formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100573 {
Ed Tanous22db1722021-06-09 10:53:51 -0700574 SecureBuffer packed{new Buffer{}};
Ed Tanouse662eae2022-01-25 10:39:19 -0800575 if (formatter != nullptr)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100576 {
Ed Tanous22db1722021-06-09 10:53:51 -0700577 formatter(credentials.user(), credentials.password(), *packed);
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100578 }
579
Ed Tanous22db1722021-06-09 10:53:51 -0700580 return packed;
581 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100582
Ed Tanous22db1722021-06-09 10:53:51 -0700583 private:
584 Credentials credentials;
585};
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100586
Ed Tanous22db1722021-06-09 10:53:51 -0700587// Wrapper for boost::async_pipe ensuring proper pipe cleanup
588template <typename Buffer>
589class Pipe
590{
591 public:
592 using unix_fd = sdbusplus::message::unix_fd;
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100593
Ed Tanous8a592812022-06-04 09:06:59 -0700594 Pipe(boost::asio::io_context& io, Buffer&& bufferIn) :
595 impl(io), buffer{std::move(bufferIn)}
Ed Tanous22db1722021-06-09 10:53:51 -0700596 {}
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100597
Ed Tanous22db1722021-06-09 10:53:51 -0700598 ~Pipe()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100599 {
Ed Tanous22db1722021-06-09 10:53:51 -0700600 // Named pipe needs to be explicitly removed
601 impl.close();
602 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100603
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800604 Pipe(const Pipe&) = delete;
605 Pipe(Pipe&&) = delete;
606 Pipe& operator=(const Pipe&) = delete;
607 Pipe& operator=(Pipe&&) = delete;
608
Ed Tanous22db1722021-06-09 10:53:51 -0700609 unix_fd fd()
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200610 {
Ed Tanous22db1722021-06-09 10:53:51 -0700611 return unix_fd{impl.native_source()};
612 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100613
Ed Tanous22db1722021-06-09 10:53:51 -0700614 template <typename WriteHandler>
615 void asyncWrite(WriteHandler&& handler)
616 {
617 impl.async_write_some(data(), std::forward<WriteHandler>(handler));
618 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100619
Ed Tanous22db1722021-06-09 10:53:51 -0700620 private:
621 // Specialization for pointer types
622 template <typename B = Buffer>
623 typename std::enable_if<boost::has_dereference<B>::value,
624 boost::asio::const_buffer>::type
625 data()
626 {
627 return boost::asio::buffer(*buffer);
628 }
629
630 template <typename B = Buffer>
631 typename std::enable_if<!boost::has_dereference<B>::value,
632 boost::asio::const_buffer>::type
633 data()
634 {
635 return boost::asio::buffer(buffer);
636 }
637
638 const std::string name;
639 boost::process::async_pipe impl;
640 Buffer buffer;
641};
642
643/**
644 * @brief Function transceives data with dbus directly.
645 *
646 * All BMC state properties will be retrieved before sending reset request.
647 */
648inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
649 const std::string& service, const std::string& name,
650 const std::string& imageUrl, const bool rw,
651 std::string&& userName, std::string&& password)
652{
653 using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
654 constexpr const size_t secretLimit = 1024;
655
656 std::shared_ptr<SecurePipe> secretPipe;
Ed Tanous168e20c2021-12-13 14:39:53 -0800657 dbus::utility::DbusVariantType unixFd = -1;
Ed Tanous22db1722021-06-09 10:53:51 -0700658
659 if (!userName.empty() || !password.empty())
660 {
661 // Encapsulate in safe buffer
662 CredentialsProvider credentials(std::move(userName),
663 std::move(password));
664
665 // Payload must contain data + NULL delimiters
666 if (credentials.user().size() + credentials.password().size() + 2 >
667 secretLimit)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100668 {
Ed Tanous22db1722021-06-09 10:53:51 -0700669 BMCWEB_LOG_ERROR << "Credentials too long to handle";
670 messages::unrecognizedRequestBody(asyncResp->res);
671 return;
672 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100673
Ed Tanous22db1722021-06-09 10:53:51 -0700674 // Pack secret
675 auto secret = credentials.pack(
676 [](const auto& user, const auto& pass, auto& buff) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700677 std::copy(user.begin(), user.end(), std::back_inserter(buff));
678 buff.push_back('\0');
679 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
680 buff.push_back('\0');
681 });
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100682
Ed Tanous22db1722021-06-09 10:53:51 -0700683 // Open pipe
684 secretPipe = std::make_shared<SecurePipe>(
685 crow::connections::systemBus->get_io_context(), std::move(secret));
686 unixFd = secretPipe->fd();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100687
Ed Tanous22db1722021-06-09 10:53:51 -0700688 // Pass secret over pipe
689 secretPipe->asyncWrite(
690 [asyncResp](const boost::system::error_code& ec, std::size_t) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700691 if (ec)
692 {
693 BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
694 messages::internalError(asyncResp->res);
695 }
696 });
Ed Tanous22db1722021-06-09 10:53:51 -0700697 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100698
Ed Tanous22db1722021-06-09 10:53:51 -0700699 crow::connections::systemBus->async_method_call(
700 [asyncResp, secretPipe](const boost::system::error_code ec,
701 bool success) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700702 if (ec)
703 {
704 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
705 messages::internalError(asyncResp->res);
706 }
707 else if (!success)
708 {
709 BMCWEB_LOG_ERROR << "Service responded with error";
710 messages::generalError(asyncResp->res);
711 }
Ed Tanous22db1722021-06-09 10:53:51 -0700712 },
713 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
714 "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
715 unixFd);
716}
717
718/**
719 * @brief Function transceives data with dbus directly.
720 *
721 * All BMC state properties will be retrieved before sending reset request.
722 */
723inline void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
724 const std::string& service, const std::string& name,
725 bool legacy)
726{
727
728 // Legacy mount requires parameter with image
729 if (legacy)
730 {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100731 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700732 [asyncResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700733 if (ec)
734 {
735 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700736
Ed Tanous002d39b2022-05-31 08:59:27 -0700737 messages::internalError(asyncResp->res);
738 return;
739 }
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100740 },
741 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
Ed Tanous22db1722021-06-09 10:53:51 -0700742 "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200743 }
Ed Tanous22db1722021-06-09 10:53:51 -0700744 else // proxy
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200745 {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200746 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700747 [asyncResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700748 if (ec)
749 {
750 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700751
Ed Tanous002d39b2022-05-31 08:59:27 -0700752 messages::internalError(asyncResp->res);
753 return;
754 }
Ed Tanous22db1722021-06-09 10:53:51 -0700755 },
756 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
757 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
758 }
759}
760
Ed Tanous96825be2022-06-03 09:43:38 -0700761inline void handleManagersVirtualMediaActionInsertPost(
762 crow::App& app, const crow::Request& req,
763 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
764 const std::string& name, const std::string& resName)
765{
766 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
767 {
768 return;
769 }
770 if (name != "bmc")
771 {
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200772 messages::resourceNotFound(asyncResp->res, "VirtualMedia.InsertMedia",
Ed Tanous96825be2022-06-03 09:43:38 -0700773 resName);
774
775 return;
776 }
777 InsertMediaActionParams actionParams;
778
779 // Read obligatory parameters (url of
780 // image)
781 if (!json_util::readJsonAction(
782 req, asyncResp->res, "Image", actionParams.imageUrl,
783 "WriteProtected", actionParams.writeProtected, "UserName",
784 actionParams.userName, "Password", actionParams.password,
785 "Inserted", actionParams.inserted, "TransferMethod",
786 actionParams.transferMethod, "TransferProtocolType",
787 actionParams.transferProtocolType))
788 {
789 BMCWEB_LOG_DEBUG << "Image is not provided";
790 return;
791 }
792
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200793 bool paramsValid = validateParams(asyncResp->res, actionParams);
Ed Tanous96825be2022-06-03 09:43:38 -0700794 if (!paramsValid)
795 {
796 return;
797 }
798
799 crow::connections::systemBus->async_method_call(
800 [asyncResp, actionParams,
801 resName](const boost::system::error_code ec,
802 const dbus::utility::MapperGetObject& getObjectType) mutable {
803 if (ec)
804 {
805 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
806 messages::internalError(asyncResp->res);
807
808 return;
809 }
810 std::string service = getObjectType.begin()->first;
811 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
812
813 crow::connections::systemBus->async_method_call(
814 [service, resName, actionParams,
Ed Tanous8a592812022-06-04 09:06:59 -0700815 asyncResp](const boost::system::error_code ec2,
Ed Tanous96825be2022-06-03 09:43:38 -0700816 dbus::utility::ManagedObjectType& subtree) mutable {
Ed Tanous8a592812022-06-04 09:06:59 -0700817 if (ec2)
Ed Tanous96825be2022-06-03 09:43:38 -0700818 {
819 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200820 messages::internalError(asyncResp->res);
Ed Tanous96825be2022-06-03 09:43:38 -0700821
822 return;
823 }
824
825 for (const auto& object : subtree)
826 {
827 const std::string& path =
828 static_cast<const std::string&>(object.first);
829
830 std::size_t lastIndex = path.rfind('/');
831 if (lastIndex == std::string::npos)
832 {
833 continue;
834 }
835
836 lastIndex += 1;
837
838 if (path.substr(lastIndex) == resName)
839 {
840 lastIndex = path.rfind("Proxy");
841 if (lastIndex != std::string::npos)
842 {
843 // Not possible in proxy mode
844 BMCWEB_LOG_DEBUG << "InsertMedia not "
845 "allowed in proxy mode";
846 messages::resourceNotFound(asyncResp->res,
847 "VirtualMedia.InsertMedia",
848 resName);
849
850 return;
851 }
852
853 lastIndex = path.rfind("Legacy");
854 if (lastIndex == std::string::npos)
855 {
856 continue;
857 }
858
859 // manager is irrelevant for
860 // VirtualMedia dbus calls
861 doMountVmLegacy(asyncResp, service, resName,
862 actionParams.imageUrl,
863 !(*actionParams.writeProtected),
864 std::move(*actionParams.userName),
865 std::move(*actionParams.password));
866
867 return;
868 }
869 }
870 BMCWEB_LOG_DEBUG << "Parent item not found";
871 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
872 },
873 service, "/xyz/openbmc_project/VirtualMedia",
874 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
875 },
876 "xyz.openbmc_project.ObjectMapper",
877 "/xyz/openbmc_project/object_mapper",
878 "xyz.openbmc_project.ObjectMapper", "GetObject",
879 "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>());
880}
881
882inline void handleManagersVirtualMediaActionEject(
883 crow::App& app, const crow::Request& req,
884 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
885 const std::string& managerName, const std::string& resName)
886{
887 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
888 {
889 return;
890 }
891 if (managerName != "bmc")
892 {
893 messages::resourceNotFound(asyncResp->res, "VirtualMedia.Eject",
894 resName);
895
896 return;
897 }
898
899 crow::connections::systemBus->async_method_call(
900 [asyncResp,
Ed Tanous8a592812022-06-04 09:06:59 -0700901 resName](const boost::system::error_code ec2,
Ed Tanous96825be2022-06-03 09:43:38 -0700902 const dbus::utility::MapperGetObject& getObjectType) {
Ed Tanous8a592812022-06-04 09:06:59 -0700903 if (ec2)
Ed Tanous96825be2022-06-03 09:43:38 -0700904 {
Ed Tanous8a592812022-06-04 09:06:59 -0700905 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec2;
Ed Tanous96825be2022-06-03 09:43:38 -0700906 messages::internalError(asyncResp->res);
907
908 return;
909 }
910 std::string service = getObjectType.begin()->first;
911 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
912
913 crow::connections::systemBus->async_method_call(
Ed Tanous02cad962022-06-30 16:50:15 -0700914 [resName, service, asyncResp{asyncResp}](
915 const boost::system::error_code ec,
916 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous96825be2022-06-03 09:43:38 -0700917 if (ec)
918 {
919 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200920 messages::internalError(asyncResp->res);
Ed Tanous96825be2022-06-03 09:43:38 -0700921
922 return;
923 }
924
925 for (const auto& object : subtree)
926 {
927 const std::string& path =
928 static_cast<const std::string&>(object.first);
929
930 std::size_t lastIndex = path.rfind('/');
931 if (lastIndex == std::string::npos)
932 {
933 continue;
934 }
935
936 lastIndex += 1;
937
938 if (path.substr(lastIndex) == resName)
939 {
940 lastIndex = path.rfind("Proxy");
941 if (lastIndex != std::string::npos)
942 {
943 // Proxy mode
944 doVmAction(asyncResp, service, resName, false);
945 }
946
947 lastIndex = path.rfind("Legacy");
948 if (lastIndex != std::string::npos)
949 {
950 // Legacy mode
951 doVmAction(asyncResp, service, resName, true);
952 }
953
954 return;
955 }
956 }
957 BMCWEB_LOG_DEBUG << "Parent item not found";
958 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
959 },
960 service, "/xyz/openbmc_project/VirtualMedia",
961 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
962 },
963 "xyz.openbmc_project.ObjectMapper",
964 "/xyz/openbmc_project/object_mapper",
965 "xyz.openbmc_project.ObjectMapper", "GetObject",
966 "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>());
967}
968
969inline void handleManagersVirtualMediaCollectionGet(
970 crow::App& app, const crow::Request& req,
971 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
972 const std::string& name)
973{
974 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
975 {
976 return;
977 }
978 if (name != "bmc")
979 {
980 messages::resourceNotFound(asyncResp->res, "VirtualMedia", name);
981
982 return;
983 }
984
985 asyncResp->res.jsonValue["@odata.type"] =
986 "#VirtualMediaCollection.VirtualMediaCollection";
987 asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
Ed Tanousfdb20342022-06-03 09:56:52 -0700988 asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
989 "redfish", "v1", "Managers", name, "VirtualMedia");
Ed Tanous96825be2022-06-03 09:43:38 -0700990
991 crow::connections::systemBus->async_method_call(
992 [asyncResp, name](const boost::system::error_code ec,
993 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);
1005 },
1006 "xyz.openbmc_project.ObjectMapper",
1007 "/xyz/openbmc_project/object_mapper",
1008 "xyz.openbmc_project.ObjectMapper", "GetObject",
1009 "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>());
1010}
1011
1012inline void
1013 handleVirtualMediaGet(crow::App& app, const crow::Request& req,
1014 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1015 const std::string& name, const std::string& resName)
1016{
1017 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1018 {
1019 return;
1020 }
1021 if (name != "bmc")
1022 {
1023 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
1024
1025 return;
1026 }
1027
1028 crow::connections::systemBus->async_method_call(
1029 [asyncResp, name,
1030 resName](const boost::system::error_code ec,
1031 const dbus::utility::MapperGetObject& getObjectType) {
1032 if (ec)
1033 {
1034 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
1035 messages::internalError(asyncResp->res);
1036
1037 return;
1038 }
1039 std::string service = getObjectType.begin()->first;
1040 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1041
1042 getVmData(asyncResp, service, name, resName);
1043 },
1044 "xyz.openbmc_project.ObjectMapper",
1045 "/xyz/openbmc_project/object_mapper",
1046 "xyz.openbmc_project.ObjectMapper", "GetObject",
1047 "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>());
1048}
1049
Ed Tanous22db1722021-06-09 10:53:51 -07001050inline void requestNBDVirtualMediaRoutes(App& app)
1051{
George Liu0fda0f12021-11-16 10:06:17 +08001052 BMCWEB_ROUTE(
1053 app,
1054 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
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 handleManagersVirtualMediaActionInsertPost, std::ref(app)));
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +02001058
George Liu0fda0f12021-11-16 10:06:17 +08001059 BMCWEB_ROUTE(
1060 app,
1061 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
Ed Tanoused398212021-06-09 17:05:54 -07001062 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous96825be2022-06-03 09:43:38 -07001063 .methods(boost::beast::http::verb::post)(std::bind_front(
1064 handleManagersVirtualMediaActionEject, std::ref(app)));
Ed Tanous002d39b2022-05-31 08:59:27 -07001065
Ed Tanous22db1722021-06-09 10:53:51 -07001066 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
Ed Tanoused398212021-06-09 17:05:54 -07001067 .privileges(redfish::privileges::getVirtualMediaCollection)
Ed Tanous96825be2022-06-03 09:43:38 -07001068 .methods(boost::beast::http::verb::get)(std::bind_front(
1069 handleManagersVirtualMediaCollectionGet, std::ref(app)));
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001070
Ed Tanous22db1722021-06-09 10:53:51 -07001071 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001072 .privileges(redfish::privileges::getVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -07001073 .methods(boost::beast::http::verb::get)(
Ed Tanous96825be2022-06-03 09:43:38 -07001074 std::bind_front(handleVirtualMediaGet, std::ref(app)));
Ed Tanous22db1722021-06-09 10:53:51 -07001075}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001076
1077} // namespace redfish