blob: 2e632f8bafb67e938a9dc1e86f8f3b45f2fcd61f [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{
Ed Tanous365a73f2023-02-24 12:16:49 -080034
35enum class VmMode
36{
37 Invalid,
38 Legacy,
39 Proxy
40};
41
42inline VmMode
43 parseObjectPathAndGetMode(const sdbusplus::message::object_path& itemPath,
44 const std::string& resName)
45{
46 std::string thisPath = itemPath.filename();
47 BMCWEB_LOG_DEBUG << "Filename: " << itemPath.str
48 << ", ThisPath: " << thisPath;
49
50 if (thisPath.empty())
51 {
52 return VmMode::Invalid;
53 }
54
55 if (thisPath != resName)
56 {
57 return VmMode::Invalid;
58 }
59
60 auto mode = itemPath.parent_path();
61 auto type = mode.parent_path();
62
63 if (mode.filename().empty() || type.filename().empty())
64 {
65 return VmMode::Invalid;
66 }
67
68 if (type.filename() != "VirtualMedia")
69 {
70 return VmMode::Invalid;
71 }
72 std::string modeStr = mode.filename();
73 if (modeStr == "Legacy")
74 {
75 return VmMode::Legacy;
76 }
77 if (modeStr == "Proxy")
78 {
79 return VmMode::Proxy;
80 }
81 return VmMode::Invalid;
82}
83
Anna Platash9e319cf2020-11-17 10:18:31 +010084/**
85 * @brief Function extracts transfer protocol name from URI.
86 */
Ed Tanous67df0732021-10-26 11:23:56 -070087inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
88{
89 boost::urls::result<boost::urls::url_view> url =
Ed Tanous079360a2022-06-29 10:05:19 -070090 boost::urls::parse_uri(imageUri);
Ed Tanous67df0732021-10-26 11:23:56 -070091 if (!url)
92 {
93 return "None";
94 }
Ed Tanous079360a2022-06-29 10:05:19 -070095 std::string_view scheme = url->scheme();
Ed Tanous67df0732021-10-26 11:23:56 -070096 if (scheme == "smb")
97 {
98 return "CIFS";
99 }
100 if (scheme == "https")
101 {
102 return "HTTPS";
103 }
104
105 return "None";
106}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200107
108/**
109 * @brief Read all known properties from VM object interfaces
110 */
Ed Tanous22db1722021-06-09 10:53:51 -0700111inline void
Ed Tanous8a592812022-06-04 09:06:59 -0700112 vmParseInterfaceObject(const dbus::utility::DBusInteracesMap& interfaces,
zhanghch058d1b46d2021-04-01 11:18:24 +0800113 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200114{
Ed Tanous8a592812022-06-04 09:06:59 -0700115 for (const auto& [interface, values] : interfaces)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200116 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800117 if (interface == "xyz.openbmc_project.VirtualMedia.MountPoint")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200118 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800119 for (const auto& [property, value] : values)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200120 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800121 if (property == "EndpointId")
122 {
123 const std::string* endpointIdValue =
124 std::get_if<std::string>(&value);
125 if (endpointIdValue == nullptr)
126 {
127 continue;
128 }
129 if (!endpointIdValue->empty())
130 {
131 // Proxy mode
132 aResp->res
133 .jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
134 *endpointIdValue;
135 aResp->res.jsonValue["TransferProtocolType"] = "OEM";
136 }
137 }
138 if (property == "ImageURL")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200139 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100140 const std::string* imageUrlValue =
Ed Tanous711ac7a2021-12-20 09:34:41 -0800141 std::get_if<std::string>(&value);
Ed Tanous26f69762022-01-25 09:49:11 -0800142 if (imageUrlValue != nullptr && !imageUrlValue->empty())
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100143 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100144 std::filesystem::path filePath = *imageUrlValue;
145 if (!filePath.has_filename())
146 {
147 // this will handle https share, which not
148 // necessarily has to have filename given.
149 aResp->res.jsonValue["ImageName"] = "";
150 }
151 else
152 {
153 aResp->res.jsonValue["ImageName"] =
154 filePath.filename();
155 }
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100156
Anna Platash9e319cf2020-11-17 10:18:31 +0100157 aResp->res.jsonValue["Image"] = *imageUrlValue;
Anna Platash9e319cf2020-11-17 10:18:31 +0100158 aResp->res.jsonValue["TransferProtocolType"] =
159 getTransferProtocolTypeFromUri(*imageUrlValue);
160
Ed Tanous711ac7a2021-12-20 09:34:41 -0800161 aResp->res.jsonValue["ConnectedVia"] = "URI";
Anna Platash9e319cf2020-11-17 10:18:31 +0100162 }
163 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800164 if (property == "WriteProtected")
Anna Platash9e319cf2020-11-17 10:18:31 +0100165 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800166 const bool* writeProtectedValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800167 if (writeProtectedValue != nullptr)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200168 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100169 aResp->res.jsonValue["WriteProtected"] =
170 *writeProtectedValue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200171 }
172 }
173 }
174 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800175 if (interface == "xyz.openbmc_project.VirtualMedia.Process")
176 {
177 for (const auto& [property, value] : values)
178 {
179 if (property == "Active")
180 {
181 const bool* activeValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800182 if (activeValue == nullptr)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800183 {
184 BMCWEB_LOG_DEBUG << "Value Active not found";
185 return;
186 }
187 aResp->res.jsonValue["Inserted"] = *activeValue;
188
Ed Tanouse05aec52022-01-25 10:28:56 -0800189 if (*activeValue)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800190 {
191 aResp->res.jsonValue["ConnectedVia"] = "Applet";
192 }
193 }
194 }
195 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200196 }
197}
198
199/**
200 * @brief Fill template for Virtual Media Item.
201 */
Ed Tanous22db1722021-06-09 10:53:51 -0700202inline nlohmann::json vmItemTemplate(const std::string& name,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500203 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200204{
205 nlohmann::json item;
Ed Tanousfdb20342022-06-03 09:56:52 -0700206 item["@odata.id"] = crow::utility::urlFromPieces(
207 "redfish", "v1", "Managers", name, "VirtualMedia", resName);
Ed Tanous22db1722021-06-09 10:53:51 -0700208
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100209 item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200210 item["Name"] = "Virtual Removable Media";
211 item["Id"] = resName;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200212 item["WriteProtected"] = true;
Ed Tanous613dabe2022-07-09 11:17:36 -0700213 item["MediaTypes"] = nlohmann::json::array_t({"CD", "USBStick"});
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200214 item["TransferMethod"] = "Stream";
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100215 item["Oem"]["OpenBMC"]["@odata.type"] =
216 "#OemVirtualMedia.v1_0_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200217
218 return item;
219}
220
221/**
222 * @brief Fills collection data
223 */
Ed Tanous22db1722021-06-09 10:53:51 -0700224inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500225 const std::string& service,
226 const std::string& name)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200227{
228 BMCWEB_LOG_DEBUG << "Get available Virtual Media resources.";
229 crow::connections::systemBus->async_method_call(
Ed Tanous02cad962022-06-30 16:50:15 -0700230 [name, aResp{std::move(aResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800231 const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700232 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700233 if (ec)
234 {
235 BMCWEB_LOG_DEBUG << "DBUS response error";
236 return;
237 }
238 nlohmann::json& members = aResp->res.jsonValue["Members"];
239 members = nlohmann::json::array();
240
241 for (const auto& object : subtree)
242 {
243 nlohmann::json item;
244 std::string path = object.first.filename();
245 if (path.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200246 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700247 continue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200248 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200249
Ed Tanousfdb20342022-06-03 09:56:52 -0700250 item["@odata.id"] = crow::utility::urlFromPieces(
251 "redfish", "v1", "Managers", name, "VirtualMedia", path);
Ed Tanous002d39b2022-05-31 08:59:27 -0700252 members.emplace_back(std::move(item));
253 }
254 aResp->res.jsonValue["Members@odata.count"] = members.size();
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200255 },
256 service, "/xyz/openbmc_project/VirtualMedia",
257 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
258}
259
260/**
261 * @brief Fills data for specific resource
262 */
Ed Tanous22db1722021-06-09 10:53:51 -0700263inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500264 const std::string& service, const std::string& name,
265 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200266{
267 BMCWEB_LOG_DEBUG << "Get Virtual Media resource data.";
268
269 crow::connections::systemBus->async_method_call(
Ed Tanous914e2d52022-01-07 11:38:34 -0800270 [resName, name,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800271 aResp](const boost::system::error_code& ec,
Ed Tanous914e2d52022-01-07 11:38:34 -0800272 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700273 if (ec)
274 {
275 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200276
Ed Tanous002d39b2022-05-31 08:59:27 -0700277 return;
278 }
279
280 for (const auto& item : subtree)
281 {
Ed Tanous365a73f2023-02-24 12:16:49 -0800282 VmMode mode = parseObjectPathAndGetMode(item.first, resName);
283 if (mode == VmMode::Invalid)
Ed Tanous002d39b2022-05-31 08:59:27 -0700284 {
285 continue;
286 }
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200287
Ed Tanous002d39b2022-05-31 08:59:27 -0700288 aResp->res.jsonValue = vmItemTemplate(name, resName);
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200289
Ed Tanous002d39b2022-05-31 08:59:27 -0700290 // Check if dbus path is Legacy type
Ed Tanous365a73f2023-02-24 12:16:49 -0800291 if (mode == VmMode::Legacy)
Ed Tanous002d39b2022-05-31 08:59:27 -0700292 {
293 aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
Ed Tanousfdb20342022-06-03 09:56:52 -0700294 ["target"] = crow::utility::urlFromPieces(
295 "redfish", "v1", "Managers", name, "VirtualMedia", resName,
296 "Actions", "VirtualMedia.InsertMedia");
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200297 }
298
Ed Tanous002d39b2022-05-31 08:59:27 -0700299 vmParseInterfaceObject(item.second, aResp);
300
301 aResp->res
302 .jsonValue["Actions"]["#VirtualMedia.EjectMedia"]["target"] =
Ed Tanousfdb20342022-06-03 09:56:52 -0700303 crow::utility::urlFromPieces("redfish", "v1", "Managers", name,
304 "VirtualMedia", resName, "Actions",
305 "VirtualMedia.EjectMedia");
Ed Tanous002d39b2022-05-31 08:59:27 -0700306 return;
307 }
308
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +0800309 messages::resourceNotFound(aResp->res, "VirtualMedia", resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200310 },
311 service, "/xyz/openbmc_project/VirtualMedia",
312 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
313}
314
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200315/**
Ed Tanous22db1722021-06-09 10:53:51 -0700316 * @brief Transfer protocols supported for InsertMedia action.
317 *
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200318 */
Ed Tanous22db1722021-06-09 10:53:51 -0700319enum class TransferProtocol
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200320{
Ed Tanous22db1722021-06-09 10:53:51 -0700321 https,
322 smb,
323 invalid
324};
325
326/**
327 * @brief Function extracts transfer protocol type from URI.
328 *
329 */
Ed Tanous67df0732021-10-26 11:23:56 -0700330inline std::optional<TransferProtocol>
Ed Tanousace85d62021-10-26 12:45:59 -0700331 getTransferProtocolFromUri(const boost::urls::url_view& imageUri)
Ed Tanous67df0732021-10-26 11:23:56 -0700332{
Ed Tanous079360a2022-06-29 10:05:19 -0700333 std::string_view scheme = imageUri.scheme();
Ed Tanous67df0732021-10-26 11:23:56 -0700334 if (scheme == "smb")
335 {
336 return TransferProtocol::smb;
337 }
338 if (scheme == "https")
339 {
340 return TransferProtocol::https;
341 }
342 if (!scheme.empty())
343 {
344 return TransferProtocol::invalid;
345 }
346
347 return {};
348}
Ed Tanous22db1722021-06-09 10:53:51 -0700349
350/**
351 * @brief Function convert transfer protocol from string param.
352 *
353 */
354inline std::optional<TransferProtocol> getTransferProtocolFromParam(
355 const std::optional<std::string>& transferProtocolType)
356{
357 if (transferProtocolType == std::nullopt)
Agata Olenderc6f4e012020-03-11 15:19:07 +0100358 {
Ed Tanous22db1722021-06-09 10:53:51 -0700359 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100360 }
361
Ed Tanous22db1722021-06-09 10:53:51 -0700362 if (*transferProtocolType == "CIFS")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200363 {
Ed Tanous22db1722021-06-09 10:53:51 -0700364 return TransferProtocol::smb;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200365 }
366
Ed Tanous22db1722021-06-09 10:53:51 -0700367 if (*transferProtocolType == "HTTPS")
368 {
369 return TransferProtocol::https;
370 }
371
372 return TransferProtocol::invalid;
373}
374
375/**
376 * @brief Function extends URI with transfer protocol type.
377 *
378 */
379inline std::string
380 getUriWithTransferProtocol(const std::string& imageUri,
381 const TransferProtocol& transferProtocol)
382{
383 if (transferProtocol == TransferProtocol::smb)
384 {
385 return "smb://" + imageUri;
386 }
387
388 if (transferProtocol == TransferProtocol::https)
389 {
390 return "https://" + imageUri;
391 }
392
393 return imageUri;
394}
395
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200396struct InsertMediaActionParams
397{
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200398 std::optional<std::string> imageUrl;
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200399 std::optional<std::string> userName;
400 std::optional<std::string> password;
401 std::optional<std::string> transferMethod;
402 std::optional<std::string> transferProtocolType;
403 std::optional<bool> writeProtected = true;
404 std::optional<bool> inserted;
405};
406
Ed Tanous22db1722021-06-09 10:53:51 -0700407template <typename T>
408static void secureCleanup(T& value)
409{
Ed Tanous4ecc6182022-01-07 09:36:26 -0800410 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
Ed Tanous22db1722021-06-09 10:53:51 -0700411 auto raw = const_cast<typename T::value_type*>(value.data());
412 explicit_bzero(raw, value.size() * sizeof(*raw));
413}
414
415class Credentials
416{
417 public:
418 Credentials(std::string&& user, std::string&& password) :
419 userBuf(std::move(user)), passBuf(std::move(password))
420 {}
421
422 ~Credentials()
423 {
424 secureCleanup(userBuf);
425 secureCleanup(passBuf);
426 }
427
428 const std::string& user()
429 {
430 return userBuf;
431 }
432
433 const std::string& password()
434 {
435 return passBuf;
436 }
437
438 Credentials() = delete;
439 Credentials(const Credentials&) = delete;
440 Credentials& operator=(const Credentials&) = delete;
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800441 Credentials(Credentials&&) = delete;
442 Credentials& operator=(Credentials&&) = delete;
Ed Tanous22db1722021-06-09 10:53:51 -0700443
444 private:
445 std::string userBuf;
446 std::string passBuf;
447};
448
449class CredentialsProvider
450{
451 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500452 template <typename T>
Ed Tanous22db1722021-06-09 10:53:51 -0700453 struct Deleter
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100454 {
Ed Tanous22db1722021-06-09 10:53:51 -0700455 void operator()(T* buff) const
456 {
457 if (buff)
458 {
459 secureCleanup(*buff);
460 delete buff;
461 }
462 }
463 };
464
465 using Buffer = std::vector<char>;
466 using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
467 // Using explicit definition instead of std::function to avoid implicit
468 // conversions eg. stack copy instead of reference
469 using FormatterFunc = void(const std::string& username,
470 const std::string& password, Buffer& dest);
471
472 CredentialsProvider(std::string&& user, std::string&& password) :
473 credentials(std::move(user), std::move(password))
474 {}
475
476 const std::string& user()
477 {
478 return credentials.user();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100479 }
480
Ed Tanous22db1722021-06-09 10:53:51 -0700481 const std::string& password()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100482 {
Ed Tanous22db1722021-06-09 10:53:51 -0700483 return credentials.password();
484 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100485
Ed Tanous1917ee92022-06-30 22:30:50 -0700486 SecureBuffer pack(FormatterFunc* formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100487 {
Ed Tanous22db1722021-06-09 10:53:51 -0700488 SecureBuffer packed{new Buffer{}};
Ed Tanouse662eae2022-01-25 10:39:19 -0800489 if (formatter != nullptr)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100490 {
Ed Tanous22db1722021-06-09 10:53:51 -0700491 formatter(credentials.user(), credentials.password(), *packed);
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100492 }
493
Ed Tanous22db1722021-06-09 10:53:51 -0700494 return packed;
495 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100496
Ed Tanous22db1722021-06-09 10:53:51 -0700497 private:
498 Credentials credentials;
499};
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100500
Ed Tanous22db1722021-06-09 10:53:51 -0700501// Wrapper for boost::async_pipe ensuring proper pipe cleanup
502template <typename Buffer>
503class Pipe
504{
505 public:
506 using unix_fd = sdbusplus::message::unix_fd;
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100507
Ed Tanous8a592812022-06-04 09:06:59 -0700508 Pipe(boost::asio::io_context& io, Buffer&& bufferIn) :
509 impl(io), buffer{std::move(bufferIn)}
Ed Tanous22db1722021-06-09 10:53:51 -0700510 {}
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100511
Ed Tanous22db1722021-06-09 10:53:51 -0700512 ~Pipe()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100513 {
Ed Tanous22db1722021-06-09 10:53:51 -0700514 // Named pipe needs to be explicitly removed
515 impl.close();
516 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100517
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800518 Pipe(const Pipe&) = delete;
519 Pipe(Pipe&&) = delete;
520 Pipe& operator=(const Pipe&) = delete;
521 Pipe& operator=(Pipe&&) = delete;
522
Ed Tanous22db1722021-06-09 10:53:51 -0700523 unix_fd fd()
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200524 {
Ed Tanous22db1722021-06-09 10:53:51 -0700525 return unix_fd{impl.native_source()};
526 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100527
Ed Tanous22db1722021-06-09 10:53:51 -0700528 template <typename WriteHandler>
529 void asyncWrite(WriteHandler&& handler)
530 {
531 impl.async_write_some(data(), std::forward<WriteHandler>(handler));
532 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100533
Ed Tanous22db1722021-06-09 10:53:51 -0700534 private:
535 // Specialization for pointer types
536 template <typename B = Buffer>
537 typename std::enable_if<boost::has_dereference<B>::value,
538 boost::asio::const_buffer>::type
539 data()
540 {
541 return boost::asio::buffer(*buffer);
542 }
543
544 template <typename B = Buffer>
545 typename std::enable_if<!boost::has_dereference<B>::value,
546 boost::asio::const_buffer>::type
547 data()
548 {
549 return boost::asio::buffer(buffer);
550 }
551
552 const std::string name;
553 boost::process::async_pipe impl;
554 Buffer buffer;
555};
556
557/**
558 * @brief Function transceives data with dbus directly.
559 *
560 * All BMC state properties will be retrieved before sending reset request.
561 */
562inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
563 const std::string& service, const std::string& name,
564 const std::string& imageUrl, const bool rw,
565 std::string&& userName, std::string&& password)
566{
567 using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
568 constexpr const size_t secretLimit = 1024;
569
570 std::shared_ptr<SecurePipe> secretPipe;
Ed Tanous168e20c2021-12-13 14:39:53 -0800571 dbus::utility::DbusVariantType unixFd = -1;
Ed Tanous22db1722021-06-09 10:53:51 -0700572
573 if (!userName.empty() || !password.empty())
574 {
575 // Encapsulate in safe buffer
576 CredentialsProvider credentials(std::move(userName),
577 std::move(password));
578
579 // Payload must contain data + NULL delimiters
580 if (credentials.user().size() + credentials.password().size() + 2 >
581 secretLimit)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100582 {
Ed Tanous22db1722021-06-09 10:53:51 -0700583 BMCWEB_LOG_ERROR << "Credentials too long to handle";
584 messages::unrecognizedRequestBody(asyncResp->res);
585 return;
586 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100587
Ed Tanous22db1722021-06-09 10:53:51 -0700588 // Pack secret
589 auto secret = credentials.pack(
590 [](const auto& user, const auto& pass, auto& buff) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700591 std::copy(user.begin(), user.end(), std::back_inserter(buff));
592 buff.push_back('\0');
593 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
594 buff.push_back('\0');
595 });
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100596
Ed Tanous22db1722021-06-09 10:53:51 -0700597 // Open pipe
598 secretPipe = std::make_shared<SecurePipe>(
599 crow::connections::systemBus->get_io_context(), std::move(secret));
600 unixFd = secretPipe->fd();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100601
Ed Tanous22db1722021-06-09 10:53:51 -0700602 // Pass secret over pipe
603 secretPipe->asyncWrite(
604 [asyncResp](const boost::system::error_code& ec, std::size_t) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700605 if (ec)
606 {
607 BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
608 messages::internalError(asyncResp->res);
609 }
610 });
Ed Tanous22db1722021-06-09 10:53:51 -0700611 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100612
Ed Tanous22db1722021-06-09 10:53:51 -0700613 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800614 [asyncResp, secretPipe](const boost::system::error_code& ec,
Ed Tanous22db1722021-06-09 10:53:51 -0700615 bool success) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700616 if (ec)
617 {
618 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
619 messages::internalError(asyncResp->res);
620 }
621 else if (!success)
622 {
623 BMCWEB_LOG_ERROR << "Service responded with error";
624 messages::generalError(asyncResp->res);
625 }
Ed Tanous22db1722021-06-09 10:53:51 -0700626 },
627 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
628 "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
629 unixFd);
630}
631
632/**
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200633 * @brief Function validate parameters of insert media request.
634 *
635 */
636inline void validateParams(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
637 const std::string& service,
638 const std::string& resName,
639 InsertMediaActionParams& actionParams)
640{
641 BMCWEB_LOG_DEBUG << "Validation started";
642 // required param imageUrl must not be empty
643 if (!actionParams.imageUrl)
644 {
645 BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
646
647 messages::propertyValueFormatError(asyncResp->res, "<empty>", "Image");
648
649 return;
650 }
651
652 // optional param inserted must be true
653 if ((actionParams.inserted != std::nullopt) && !*actionParams.inserted)
654 {
655 BMCWEB_LOG_ERROR
656 << "Request action optional parameter Inserted must be true.";
657
658 messages::actionParameterNotSupported(asyncResp->res, "Inserted",
659 "InsertMedia");
660
661 return;
662 }
663
664 // optional param transferMethod must be stream
665 if ((actionParams.transferMethod != std::nullopt) &&
666 (*actionParams.transferMethod != "Stream"))
667 {
668 BMCWEB_LOG_ERROR << "Request action optional parameter "
669 "TransferMethod must be Stream.";
670
671 messages::actionParameterNotSupported(asyncResp->res, "TransferMethod",
672 "InsertMedia");
673
674 return;
675 }
676 boost::urls::result<boost::urls::url_view> url =
677 boost::urls::parse_uri(*actionParams.imageUrl);
678 if (!url)
679 {
680 messages::actionParameterValueFormatError(
681 asyncResp->res, *actionParams.imageUrl, "Image", "InsertMedia");
682 return;
683 }
684 std::optional<TransferProtocol> uriTransferProtocolType =
685 getTransferProtocolFromUri(*url);
686
687 std::optional<TransferProtocol> paramTransferProtocolType =
688 getTransferProtocolFromParam(actionParams.transferProtocolType);
689
690 // ImageUrl does not contain valid protocol type
691 if (*uriTransferProtocolType == TransferProtocol::invalid)
692 {
693 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
694 "contain specified protocol type from list: "
695 "(smb, https).";
696
697 messages::resourceAtUriInUnknownFormat(asyncResp->res, *url);
698
699 return;
700 }
701
702 // transferProtocolType should contain value from list
703 if (*paramTransferProtocolType == TransferProtocol::invalid)
704 {
705 BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
706 "must be provided with value from list: "
707 "(CIFS, HTTPS).";
708
709 messages::propertyValueNotInList(asyncResp->res,
710 *actionParams.transferProtocolType,
711 "TransferProtocolType");
712 return;
713 }
714
715 // valid transfer protocol not provided either with URI nor param
716 if ((uriTransferProtocolType == std::nullopt) &&
717 (paramTransferProtocolType == std::nullopt))
718 {
719 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
720 "contain specified protocol type or param "
721 "TransferProtocolType must be provided.";
722
723 messages::resourceAtUriInUnknownFormat(asyncResp->res, *url);
724
725 return;
726 }
727
728 // valid transfer protocol provided both with URI and param
729 if ((paramTransferProtocolType != std::nullopt) &&
730 (uriTransferProtocolType != std::nullopt))
731 {
732 // check if protocol is the same for URI and param
733 if (*paramTransferProtocolType != *uriTransferProtocolType)
734 {
735 BMCWEB_LOG_ERROR << "Request action parameter "
736 "TransferProtocolType must contain the "
737 "same protocol type as protocol type "
738 "provided with param imageUrl.";
739
740 messages::actionParameterValueTypeError(
741 asyncResp->res, *actionParams.transferProtocolType,
742 "TransferProtocolType", "InsertMedia");
743
744 return;
745 }
746 }
747
748 // validation passed, add protocol to URI if needed
749 if (uriTransferProtocolType == std::nullopt)
750 {
751 actionParams.imageUrl = getUriWithTransferProtocol(
752 *actionParams.imageUrl, *paramTransferProtocolType);
753 }
754
755 doMountVmLegacy(asyncResp, service, resName, *actionParams.imageUrl,
756 !(*actionParams.writeProtected),
757 std::move(*actionParams.userName),
758 std::move(*actionParams.password));
759}
760
761/**
Ed Tanous22db1722021-06-09 10:53:51 -0700762 * @brief Function transceives data with dbus directly.
763 *
764 * All BMC state properties will be retrieved before sending reset request.
765 */
Ed Tanous24e740a2023-02-24 12:08:58 -0800766inline void doEjectAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
767 const std::string& service, const std::string& name,
768 bool legacy)
Ed Tanous22db1722021-06-09 10:53:51 -0700769{
770
771 // Legacy mount requires parameter with image
772 if (legacy)
773 {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100774 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800775 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700776 if (ec)
777 {
778 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700779
Ed Tanous002d39b2022-05-31 08:59:27 -0700780 messages::internalError(asyncResp->res);
781 return;
782 }
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100783 },
784 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
Ed Tanous22db1722021-06-09 10:53:51 -0700785 "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200786 }
Ed Tanous22db1722021-06-09 10:53:51 -0700787 else // proxy
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200788 {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200789 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800790 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700791 if (ec)
792 {
793 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700794
Ed Tanous002d39b2022-05-31 08:59:27 -0700795 messages::internalError(asyncResp->res);
796 return;
797 }
Ed Tanous22db1722021-06-09 10:53:51 -0700798 },
799 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
800 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
801 }
802}
803
Ed Tanous96825be2022-06-03 09:43:38 -0700804inline void handleManagersVirtualMediaActionInsertPost(
805 crow::App& app, const crow::Request& req,
806 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
807 const std::string& name, const std::string& resName)
808{
809 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
810 {
811 return;
812 }
813 if (name != "bmc")
814 {
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200815 messages::resourceNotFound(asyncResp->res, "VirtualMedia.InsertMedia",
Ed Tanous96825be2022-06-03 09:43:38 -0700816 resName);
817
818 return;
819 }
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200820 std::optional<InsertMediaActionParams> actionParams =
821 InsertMediaActionParams();
Ed Tanous96825be2022-06-03 09:43:38 -0700822
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200823 // Read obligatory parameters (url of image)
Ed Tanous96825be2022-06-03 09:43:38 -0700824 if (!json_util::readJsonAction(
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200825 req, asyncResp->res, "Image", actionParams->imageUrl,
826 "WriteProtected", actionParams->writeProtected, "UserName",
827 actionParams->userName, "Password", actionParams->password,
828 "Inserted", actionParams->inserted, "TransferMethod",
829 actionParams->transferMethod, "TransferProtocolType",
830 actionParams->transferProtocolType))
Ed Tanous96825be2022-06-03 09:43:38 -0700831 {
832 return;
833 }
834
George Liu2b731192023-01-11 16:27:13 +0800835 dbus::utility::getDbusObject(
836 "/xyz/openbmc_project/VirtualMedia", {},
Ed Tanous96825be2022-06-03 09:43:38 -0700837 [asyncResp, actionParams,
George Liu2b731192023-01-11 16:27:13 +0800838 resName](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -0700839 const dbus::utility::MapperGetObject& getObjectType) mutable {
840 if (ec)
841 {
842 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
843 messages::internalError(asyncResp->res);
844
845 return;
846 }
847 std::string service = getObjectType.begin()->first;
848 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
849
850 crow::connections::systemBus->async_method_call(
851 [service, resName, actionParams,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800852 asyncResp](const boost::system::error_code& ec2,
Ed Tanous96825be2022-06-03 09:43:38 -0700853 dbus::utility::ManagedObjectType& subtree) mutable {
Ed Tanous8a592812022-06-04 09:06:59 -0700854 if (ec2)
Ed Tanous96825be2022-06-03 09:43:38 -0700855 {
856 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200857 messages::internalError(asyncResp->res);
Ed Tanous96825be2022-06-03 09:43:38 -0700858
859 return;
860 }
861
862 for (const auto& object : subtree)
863 {
Ed Tanous365a73f2023-02-24 12:16:49 -0800864 VmMode mode = parseObjectPathAndGetMode(object.first, resName);
865 if (mode == VmMode::Proxy)
Ed Tanous96825be2022-06-03 09:43:38 -0700866 {
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200867 validateParams(asyncResp, service, resName, *actionParams);
Ed Tanous96825be2022-06-03 09:43:38 -0700868
869 return;
870 }
871 }
872 BMCWEB_LOG_DEBUG << "Parent item not found";
873 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
874 },
875 service, "/xyz/openbmc_project/VirtualMedia",
876 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
George Liu2b731192023-01-11 16:27:13 +0800877 });
Ed Tanous96825be2022-06-03 09:43:38 -0700878}
879
880inline void handleManagersVirtualMediaActionEject(
881 crow::App& app, const crow::Request& req,
882 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
883 const std::string& managerName, const std::string& resName)
884{
885 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
886 {
887 return;
888 }
889 if (managerName != "bmc")
890 {
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200891 messages::resourceNotFound(asyncResp->res, "VirtualMedia.EjectMedia",
Ed Tanous96825be2022-06-03 09:43:38 -0700892 resName);
893
894 return;
895 }
896
George Liu2b731192023-01-11 16:27:13 +0800897 dbus::utility::getDbusObject(
898 "/xyz/openbmc_project/VirtualMedia", {},
Ed Tanous96825be2022-06-03 09:43:38 -0700899 [asyncResp,
George Liu2b731192023-01-11 16:27:13 +0800900 resName](const boost::system::error_code& ec2,
Ed Tanous96825be2022-06-03 09:43:38 -0700901 const dbus::utility::MapperGetObject& getObjectType) {
Ed Tanous8a592812022-06-04 09:06:59 -0700902 if (ec2)
Ed Tanous96825be2022-06-03 09:43:38 -0700903 {
Ed Tanous8a592812022-06-04 09:06:59 -0700904 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec2;
Ed Tanous96825be2022-06-03 09:43:38 -0700905 messages::internalError(asyncResp->res);
906
907 return;
908 }
909 std::string service = getObjectType.begin()->first;
910 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
911
912 crow::connections::systemBus->async_method_call(
Ed Tanous02cad962022-06-30 16:50:15 -0700913 [resName, service, asyncResp{asyncResp}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800914 const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700915 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous96825be2022-06-03 09:43:38 -0700916 if (ec)
917 {
918 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200919 messages::internalError(asyncResp->res);
Ed Tanous96825be2022-06-03 09:43:38 -0700920
921 return;
922 }
923
924 for (const auto& object : subtree)
925 {
Ed Tanous96825be2022-06-03 09:43:38 -0700926
Ed Tanous365a73f2023-02-24 12:16:49 -0800927 VmMode mode = parseObjectPathAndGetMode(object.first, resName);
928 if (mode != VmMode::Invalid)
Ed Tanous96825be2022-06-03 09:43:38 -0700929 {
Ed Tanous365a73f2023-02-24 12:16:49 -0800930 doEjectAction(asyncResp, service, resName,
931 mode == VmMode::Legacy);
Ed Tanous96825be2022-06-03 09:43:38 -0700932 }
933 }
934 BMCWEB_LOG_DEBUG << "Parent item not found";
935 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
936 },
937 service, "/xyz/openbmc_project/VirtualMedia",
938 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
George Liu2b731192023-01-11 16:27:13 +0800939 });
Ed Tanous96825be2022-06-03 09:43:38 -0700940}
941
942inline void handleManagersVirtualMediaCollectionGet(
943 crow::App& app, const crow::Request& req,
944 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
945 const std::string& name)
946{
947 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
948 {
949 return;
950 }
951 if (name != "bmc")
952 {
953 messages::resourceNotFound(asyncResp->res, "VirtualMedia", name);
954
955 return;
956 }
957
958 asyncResp->res.jsonValue["@odata.type"] =
959 "#VirtualMediaCollection.VirtualMediaCollection";
960 asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
Ed Tanousfdb20342022-06-03 09:56:52 -0700961 asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
962 "redfish", "v1", "Managers", name, "VirtualMedia");
Ed Tanous96825be2022-06-03 09:43:38 -0700963
George Liu2b731192023-01-11 16:27:13 +0800964 dbus::utility::getDbusObject(
965 "/xyz/openbmc_project/VirtualMedia", {},
966 [asyncResp, name](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -0700967 const dbus::utility::MapperGetObject& getObjectType) {
968 if (ec)
969 {
970 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
971 messages::internalError(asyncResp->res);
972
973 return;
974 }
975 std::string service = getObjectType.begin()->first;
976 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
977
978 getVmResourceList(asyncResp, service, name);
George Liu2b731192023-01-11 16:27:13 +0800979 });
Ed Tanous96825be2022-06-03 09:43:38 -0700980}
981
982inline void
983 handleVirtualMediaGet(crow::App& app, const crow::Request& req,
984 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
985 const std::string& name, const std::string& resName)
986{
987 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
988 {
989 return;
990 }
991 if (name != "bmc")
992 {
993 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
994
995 return;
996 }
997
George Liu2b731192023-01-11 16:27:13 +0800998 dbus::utility::getDbusObject(
999 "/xyz/openbmc_project/VirtualMedia", {},
Ed Tanous96825be2022-06-03 09:43:38 -07001000 [asyncResp, name,
George Liu2b731192023-01-11 16:27:13 +08001001 resName](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -07001002 const dbus::utility::MapperGetObject& getObjectType) {
1003 if (ec)
1004 {
1005 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
1006 messages::internalError(asyncResp->res);
1007
1008 return;
1009 }
1010 std::string service = getObjectType.begin()->first;
1011 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1012
1013 getVmData(asyncResp, service, name, resName);
George Liu2b731192023-01-11 16:27:13 +08001014 });
Ed Tanous96825be2022-06-03 09:43:38 -07001015}
1016
Ed Tanous22db1722021-06-09 10:53:51 -07001017inline void requestNBDVirtualMediaRoutes(App& app)
1018{
George Liu0fda0f12021-11-16 10:06:17 +08001019 BMCWEB_ROUTE(
1020 app,
1021 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
Ed Tanoused398212021-06-09 17:05:54 -07001022 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous96825be2022-06-03 09:43:38 -07001023 .methods(boost::beast::http::verb::post)(std::bind_front(
1024 handleManagersVirtualMediaActionInsertPost, std::ref(app)));
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +02001025
George Liu0fda0f12021-11-16 10:06:17 +08001026 BMCWEB_ROUTE(
1027 app,
1028 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
Ed Tanoused398212021-06-09 17:05:54 -07001029 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous96825be2022-06-03 09:43:38 -07001030 .methods(boost::beast::http::verb::post)(std::bind_front(
1031 handleManagersVirtualMediaActionEject, std::ref(app)));
Ed Tanous002d39b2022-05-31 08:59:27 -07001032
Ed Tanous22db1722021-06-09 10:53:51 -07001033 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
Ed Tanoused398212021-06-09 17:05:54 -07001034 .privileges(redfish::privileges::getVirtualMediaCollection)
Ed Tanous96825be2022-06-03 09:43:38 -07001035 .methods(boost::beast::http::verb::get)(std::bind_front(
1036 handleManagersVirtualMediaCollectionGet, std::ref(app)));
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001037
Ed Tanous22db1722021-06-09 10:53:51 -07001038 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001039 .privileges(redfish::privileges::getVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -07001040 .methods(boost::beast::http::verb::get)(
Ed Tanous96825be2022-06-03 09:43:38 -07001041 std::bind_front(handleVirtualMediaGet, std::ref(app)));
Ed Tanous22db1722021-06-09 10:53:51 -07001042}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001043
1044} // namespace redfish