blob: 405de7782562a82d174d15ea2e6b9b075c0443f0 [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 Tanous739b87e2023-02-24 13:13:33 -080021#include "generated/enums/virtual_media.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080022#include "query.hpp"
23#include "registries/privilege_registry.hpp"
24#include "utils/json_utils.hpp"
25
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +010026#include <boost/process/async_pipe.hpp>
27#include <boost/type_traits/has_dereference.hpp>
Anna Platash9e319cf2020-11-17 10:18:31 +010028#include <boost/url/url_view.hpp>
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020029
George Liu2b731192023-01-11 16:27:13 +080030#include <array>
31#include <string_view>
32
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020033namespace redfish
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020034{
Ed Tanous365a73f2023-02-24 12:16:49 -080035
36enum class VmMode
37{
38 Invalid,
39 Legacy,
40 Proxy
41};
42
43inline VmMode
44 parseObjectPathAndGetMode(const sdbusplus::message::object_path& itemPath,
45 const std::string& resName)
46{
47 std::string thisPath = itemPath.filename();
48 BMCWEB_LOG_DEBUG << "Filename: " << itemPath.str
49 << ", ThisPath: " << thisPath;
50
51 if (thisPath.empty())
52 {
53 return VmMode::Invalid;
54 }
55
56 if (thisPath != resName)
57 {
58 return VmMode::Invalid;
59 }
60
61 auto mode = itemPath.parent_path();
62 auto type = mode.parent_path();
63
64 if (mode.filename().empty() || type.filename().empty())
65 {
66 return VmMode::Invalid;
67 }
68
69 if (type.filename() != "VirtualMedia")
70 {
71 return VmMode::Invalid;
72 }
73 std::string modeStr = mode.filename();
74 if (modeStr == "Legacy")
75 {
76 return VmMode::Legacy;
77 }
78 if (modeStr == "Proxy")
79 {
80 return VmMode::Proxy;
81 }
82 return VmMode::Invalid;
83}
84
Anna Platash9e319cf2020-11-17 10:18:31 +010085/**
86 * @brief Function extracts transfer protocol name from URI.
87 */
Ed Tanous67df0732021-10-26 11:23:56 -070088inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
89{
90 boost::urls::result<boost::urls::url_view> url =
Ed Tanous079360a2022-06-29 10:05:19 -070091 boost::urls::parse_uri(imageUri);
Ed Tanous67df0732021-10-26 11:23:56 -070092 if (!url)
93 {
94 return "None";
95 }
Ed Tanous079360a2022-06-29 10:05:19 -070096 std::string_view scheme = url->scheme();
Ed Tanous67df0732021-10-26 11:23:56 -070097 if (scheme == "smb")
98 {
99 return "CIFS";
100 }
101 if (scheme == "https")
102 {
103 return "HTTPS";
104 }
105
106 return "None";
107}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200108
109/**
110 * @brief Read all known properties from VM object interfaces
111 */
Ed Tanous22db1722021-06-09 10:53:51 -0700112inline void
Ed Tanous8a592812022-06-04 09:06:59 -0700113 vmParseInterfaceObject(const dbus::utility::DBusInteracesMap& interfaces,
zhanghch058d1b46d2021-04-01 11:18:24 +0800114 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200115{
Ed Tanous8a592812022-06-04 09:06:59 -0700116 for (const auto& [interface, values] : interfaces)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200117 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800118 if (interface == "xyz.openbmc_project.VirtualMedia.MountPoint")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200119 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800120 for (const auto& [property, value] : values)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200121 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800122 if (property == "EndpointId")
123 {
124 const std::string* endpointIdValue =
125 std::get_if<std::string>(&value);
126 if (endpointIdValue == nullptr)
127 {
128 continue;
129 }
130 if (!endpointIdValue->empty())
131 {
132 // Proxy mode
133 aResp->res
134 .jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
135 *endpointIdValue;
136 aResp->res.jsonValue["TransferProtocolType"] = "OEM";
137 }
138 }
139 if (property == "ImageURL")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200140 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100141 const std::string* imageUrlValue =
Ed Tanous711ac7a2021-12-20 09:34:41 -0800142 std::get_if<std::string>(&value);
Ed Tanous26f69762022-01-25 09:49:11 -0800143 if (imageUrlValue != nullptr && !imageUrlValue->empty())
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100144 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100145 std::filesystem::path filePath = *imageUrlValue;
146 if (!filePath.has_filename())
147 {
148 // this will handle https share, which not
149 // necessarily has to have filename given.
150 aResp->res.jsonValue["ImageName"] = "";
151 }
152 else
153 {
154 aResp->res.jsonValue["ImageName"] =
155 filePath.filename();
156 }
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100157
Anna Platash9e319cf2020-11-17 10:18:31 +0100158 aResp->res.jsonValue["Image"] = *imageUrlValue;
Anna Platash9e319cf2020-11-17 10:18:31 +0100159 aResp->res.jsonValue["TransferProtocolType"] =
160 getTransferProtocolTypeFromUri(*imageUrlValue);
161
Ed Tanous739b87e2023-02-24 13:13:33 -0800162 aResp->res.jsonValue["ConnectedVia"] =
163 virtual_media::ConnectedVia::URI;
Anna Platash9e319cf2020-11-17 10:18:31 +0100164 }
165 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800166 if (property == "WriteProtected")
Anna Platash9e319cf2020-11-17 10:18:31 +0100167 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800168 const bool* writeProtectedValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800169 if (writeProtectedValue != nullptr)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200170 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100171 aResp->res.jsonValue["WriteProtected"] =
172 *writeProtectedValue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200173 }
174 }
175 }
176 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800177 if (interface == "xyz.openbmc_project.VirtualMedia.Process")
178 {
179 for (const auto& [property, value] : values)
180 {
181 if (property == "Active")
182 {
183 const bool* activeValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800184 if (activeValue == nullptr)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800185 {
186 BMCWEB_LOG_DEBUG << "Value Active not found";
187 return;
188 }
189 aResp->res.jsonValue["Inserted"] = *activeValue;
190
Ed Tanouse05aec52022-01-25 10:28:56 -0800191 if (*activeValue)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800192 {
Ed Tanous739b87e2023-02-24 13:13:33 -0800193 aResp->res.jsonValue["ConnectedVia"] =
194 virtual_media::ConnectedVia::Applet;
Ed Tanous711ac7a2021-12-20 09:34:41 -0800195 }
196 }
197 }
198 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200199 }
200}
201
202/**
203 * @brief Fill template for Virtual Media Item.
204 */
Ed Tanous22db1722021-06-09 10:53:51 -0700205inline nlohmann::json vmItemTemplate(const std::string& name,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500206 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200207{
208 nlohmann::json item;
Ed Tanousfdb20342022-06-03 09:56:52 -0700209 item["@odata.id"] = crow::utility::urlFromPieces(
210 "redfish", "v1", "Managers", name, "VirtualMedia", resName);
Ed Tanous22db1722021-06-09 10:53:51 -0700211
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100212 item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200213 item["Name"] = "Virtual Removable Media";
214 item["Id"] = resName;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200215 item["WriteProtected"] = true;
Ed Tanous739b87e2023-02-24 13:13:33 -0800216 item["ConnectedVia"] = virtual_media::ConnectedVia::NotConnected;
Ed Tanous613dabe2022-07-09 11:17:36 -0700217 item["MediaTypes"] = nlohmann::json::array_t({"CD", "USBStick"});
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200218 item["TransferMethod"] = "Stream";
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100219 item["Oem"]["OpenBMC"]["@odata.type"] =
220 "#OemVirtualMedia.v1_0_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200221
222 return item;
223}
224
225/**
226 * @brief Fills collection data
227 */
Ed Tanous22db1722021-06-09 10:53:51 -0700228inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500229 const std::string& service,
230 const std::string& name)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200231{
232 BMCWEB_LOG_DEBUG << "Get available Virtual Media resources.";
233 crow::connections::systemBus->async_method_call(
Ed Tanous02cad962022-06-30 16:50:15 -0700234 [name, aResp{std::move(aResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800235 const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700236 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700237 if (ec)
238 {
239 BMCWEB_LOG_DEBUG << "DBUS response error";
240 return;
241 }
242 nlohmann::json& members = aResp->res.jsonValue["Members"];
243 members = nlohmann::json::array();
244
245 for (const auto& object : subtree)
246 {
247 nlohmann::json item;
248 std::string path = object.first.filename();
249 if (path.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200250 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700251 continue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200252 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200253
Ed Tanousfdb20342022-06-03 09:56:52 -0700254 item["@odata.id"] = crow::utility::urlFromPieces(
255 "redfish", "v1", "Managers", name, "VirtualMedia", path);
Ed Tanous002d39b2022-05-31 08:59:27 -0700256 members.emplace_back(std::move(item));
257 }
258 aResp->res.jsonValue["Members@odata.count"] = members.size();
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200259 },
260 service, "/xyz/openbmc_project/VirtualMedia",
261 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
262}
263
264/**
265 * @brief Fills data for specific resource
266 */
Ed Tanous22db1722021-06-09 10:53:51 -0700267inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500268 const std::string& service, const std::string& name,
269 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200270{
271 BMCWEB_LOG_DEBUG << "Get Virtual Media resource data.";
272
273 crow::connections::systemBus->async_method_call(
Ed Tanous914e2d52022-01-07 11:38:34 -0800274 [resName, name,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800275 aResp](const boost::system::error_code& ec,
Ed Tanous914e2d52022-01-07 11:38:34 -0800276 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700277 if (ec)
278 {
279 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200280
Ed Tanous002d39b2022-05-31 08:59:27 -0700281 return;
282 }
283
284 for (const auto& item : subtree)
285 {
Ed Tanous365a73f2023-02-24 12:16:49 -0800286 VmMode mode = parseObjectPathAndGetMode(item.first, resName);
287 if (mode == VmMode::Invalid)
Ed Tanous002d39b2022-05-31 08:59:27 -0700288 {
289 continue;
290 }
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200291
Ed Tanous002d39b2022-05-31 08:59:27 -0700292 aResp->res.jsonValue = vmItemTemplate(name, resName);
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200293
Ed Tanous002d39b2022-05-31 08:59:27 -0700294 // Check if dbus path is Legacy type
Ed Tanous365a73f2023-02-24 12:16:49 -0800295 if (mode == VmMode::Legacy)
Ed Tanous002d39b2022-05-31 08:59:27 -0700296 {
297 aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
Ed Tanousfdb20342022-06-03 09:56:52 -0700298 ["target"] = crow::utility::urlFromPieces(
299 "redfish", "v1", "Managers", name, "VirtualMedia", resName,
300 "Actions", "VirtualMedia.InsertMedia");
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200301 }
302
Ed Tanous002d39b2022-05-31 08:59:27 -0700303 vmParseInterfaceObject(item.second, aResp);
304
305 aResp->res
306 .jsonValue["Actions"]["#VirtualMedia.EjectMedia"]["target"] =
Ed Tanousfdb20342022-06-03 09:56:52 -0700307 crow::utility::urlFromPieces("redfish", "v1", "Managers", name,
308 "VirtualMedia", resName, "Actions",
309 "VirtualMedia.EjectMedia");
Ed Tanous002d39b2022-05-31 08:59:27 -0700310 return;
311 }
312
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +0800313 messages::resourceNotFound(aResp->res, "VirtualMedia", resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200314 },
315 service, "/xyz/openbmc_project/VirtualMedia",
316 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
317}
318
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200319/**
Ed Tanous22db1722021-06-09 10:53:51 -0700320 * @brief Transfer protocols supported for InsertMedia action.
321 *
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200322 */
Ed Tanous22db1722021-06-09 10:53:51 -0700323enum class TransferProtocol
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200324{
Ed Tanous22db1722021-06-09 10:53:51 -0700325 https,
326 smb,
327 invalid
328};
329
330/**
331 * @brief Function extracts transfer protocol type from URI.
332 *
333 */
Ed Tanous67df0732021-10-26 11:23:56 -0700334inline std::optional<TransferProtocol>
Ed Tanousace85d62021-10-26 12:45:59 -0700335 getTransferProtocolFromUri(const boost::urls::url_view& imageUri)
Ed Tanous67df0732021-10-26 11:23:56 -0700336{
Ed Tanous079360a2022-06-29 10:05:19 -0700337 std::string_view scheme = imageUri.scheme();
Ed Tanous67df0732021-10-26 11:23:56 -0700338 if (scheme == "smb")
339 {
340 return TransferProtocol::smb;
341 }
342 if (scheme == "https")
343 {
344 return TransferProtocol::https;
345 }
346 if (!scheme.empty())
347 {
348 return TransferProtocol::invalid;
349 }
350
351 return {};
352}
Ed Tanous22db1722021-06-09 10:53:51 -0700353
354/**
355 * @brief Function convert transfer protocol from string param.
356 *
357 */
358inline std::optional<TransferProtocol> getTransferProtocolFromParam(
359 const std::optional<std::string>& transferProtocolType)
360{
361 if (transferProtocolType == std::nullopt)
Agata Olenderc6f4e012020-03-11 15:19:07 +0100362 {
Ed Tanous22db1722021-06-09 10:53:51 -0700363 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100364 }
365
Ed Tanous22db1722021-06-09 10:53:51 -0700366 if (*transferProtocolType == "CIFS")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200367 {
Ed Tanous22db1722021-06-09 10:53:51 -0700368 return TransferProtocol::smb;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200369 }
370
Ed Tanous22db1722021-06-09 10:53:51 -0700371 if (*transferProtocolType == "HTTPS")
372 {
373 return TransferProtocol::https;
374 }
375
376 return TransferProtocol::invalid;
377}
378
379/**
380 * @brief Function extends URI with transfer protocol type.
381 *
382 */
383inline std::string
384 getUriWithTransferProtocol(const std::string& imageUri,
385 const TransferProtocol& transferProtocol)
386{
387 if (transferProtocol == TransferProtocol::smb)
388 {
389 return "smb://" + imageUri;
390 }
391
392 if (transferProtocol == TransferProtocol::https)
393 {
394 return "https://" + imageUri;
395 }
396
397 return imageUri;
398}
399
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200400struct InsertMediaActionParams
401{
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200402 std::optional<std::string> imageUrl;
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200403 std::optional<std::string> userName;
404 std::optional<std::string> password;
405 std::optional<std::string> transferMethod;
406 std::optional<std::string> transferProtocolType;
407 std::optional<bool> writeProtected = true;
408 std::optional<bool> inserted;
409};
410
Ed Tanous22db1722021-06-09 10:53:51 -0700411template <typename T>
412static void secureCleanup(T& value)
413{
Ed Tanous4ecc6182022-01-07 09:36:26 -0800414 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
Ed Tanous22db1722021-06-09 10:53:51 -0700415 auto raw = const_cast<typename T::value_type*>(value.data());
416 explicit_bzero(raw, value.size() * sizeof(*raw));
417}
418
419class Credentials
420{
421 public:
422 Credentials(std::string&& user, std::string&& password) :
423 userBuf(std::move(user)), passBuf(std::move(password))
424 {}
425
426 ~Credentials()
427 {
428 secureCleanup(userBuf);
429 secureCleanup(passBuf);
430 }
431
432 const std::string& user()
433 {
434 return userBuf;
435 }
436
437 const std::string& password()
438 {
439 return passBuf;
440 }
441
442 Credentials() = delete;
443 Credentials(const Credentials&) = delete;
444 Credentials& operator=(const Credentials&) = delete;
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800445 Credentials(Credentials&&) = delete;
446 Credentials& operator=(Credentials&&) = delete;
Ed Tanous22db1722021-06-09 10:53:51 -0700447
448 private:
449 std::string userBuf;
450 std::string passBuf;
451};
452
453class CredentialsProvider
454{
455 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500456 template <typename T>
Ed Tanous22db1722021-06-09 10:53:51 -0700457 struct Deleter
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100458 {
Ed Tanous22db1722021-06-09 10:53:51 -0700459 void operator()(T* buff) const
460 {
461 if (buff)
462 {
463 secureCleanup(*buff);
464 delete buff;
465 }
466 }
467 };
468
469 using Buffer = std::vector<char>;
470 using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
471 // Using explicit definition instead of std::function to avoid implicit
472 // conversions eg. stack copy instead of reference
473 using FormatterFunc = void(const std::string& username,
474 const std::string& password, Buffer& dest);
475
476 CredentialsProvider(std::string&& user, std::string&& password) :
477 credentials(std::move(user), std::move(password))
478 {}
479
480 const std::string& user()
481 {
482 return credentials.user();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100483 }
484
Ed Tanous22db1722021-06-09 10:53:51 -0700485 const std::string& password()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100486 {
Ed Tanous22db1722021-06-09 10:53:51 -0700487 return credentials.password();
488 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100489
Ed Tanous1917ee92022-06-30 22:30:50 -0700490 SecureBuffer pack(FormatterFunc* formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100491 {
Ed Tanous22db1722021-06-09 10:53:51 -0700492 SecureBuffer packed{new Buffer{}};
Ed Tanouse662eae2022-01-25 10:39:19 -0800493 if (formatter != nullptr)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100494 {
Ed Tanous22db1722021-06-09 10:53:51 -0700495 formatter(credentials.user(), credentials.password(), *packed);
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100496 }
497
Ed Tanous22db1722021-06-09 10:53:51 -0700498 return packed;
499 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100500
Ed Tanous22db1722021-06-09 10:53:51 -0700501 private:
502 Credentials credentials;
503};
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100504
Ed Tanous22db1722021-06-09 10:53:51 -0700505// Wrapper for boost::async_pipe ensuring proper pipe cleanup
506template <typename Buffer>
507class Pipe
508{
509 public:
510 using unix_fd = sdbusplus::message::unix_fd;
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100511
Ed Tanous8a592812022-06-04 09:06:59 -0700512 Pipe(boost::asio::io_context& io, Buffer&& bufferIn) :
513 impl(io), buffer{std::move(bufferIn)}
Ed Tanous22db1722021-06-09 10:53:51 -0700514 {}
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100515
Ed Tanous22db1722021-06-09 10:53:51 -0700516 ~Pipe()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100517 {
Ed Tanous22db1722021-06-09 10:53:51 -0700518 // Named pipe needs to be explicitly removed
519 impl.close();
520 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100521
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800522 Pipe(const Pipe&) = delete;
523 Pipe(Pipe&&) = delete;
524 Pipe& operator=(const Pipe&) = delete;
525 Pipe& operator=(Pipe&&) = delete;
526
Ed Tanous22db1722021-06-09 10:53:51 -0700527 unix_fd fd()
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200528 {
Ed Tanous22db1722021-06-09 10:53:51 -0700529 return unix_fd{impl.native_source()};
530 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100531
Ed Tanous22db1722021-06-09 10:53:51 -0700532 template <typename WriteHandler>
533 void asyncWrite(WriteHandler&& handler)
534 {
535 impl.async_write_some(data(), std::forward<WriteHandler>(handler));
536 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100537
Ed Tanous22db1722021-06-09 10:53:51 -0700538 private:
539 // Specialization for pointer types
540 template <typename B = Buffer>
541 typename std::enable_if<boost::has_dereference<B>::value,
542 boost::asio::const_buffer>::type
543 data()
544 {
545 return boost::asio::buffer(*buffer);
546 }
547
548 template <typename B = Buffer>
549 typename std::enable_if<!boost::has_dereference<B>::value,
550 boost::asio::const_buffer>::type
551 data()
552 {
553 return boost::asio::buffer(buffer);
554 }
555
556 const std::string name;
557 boost::process::async_pipe impl;
558 Buffer buffer;
559};
560
561/**
562 * @brief Function transceives data with dbus directly.
563 *
564 * All BMC state properties will be retrieved before sending reset request.
565 */
566inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
567 const std::string& service, const std::string& name,
568 const std::string& imageUrl, const bool rw,
569 std::string&& userName, std::string&& password)
570{
571 using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
572 constexpr const size_t secretLimit = 1024;
573
574 std::shared_ptr<SecurePipe> secretPipe;
Ed Tanous168e20c2021-12-13 14:39:53 -0800575 dbus::utility::DbusVariantType unixFd = -1;
Ed Tanous22db1722021-06-09 10:53:51 -0700576
577 if (!userName.empty() || !password.empty())
578 {
579 // Encapsulate in safe buffer
580 CredentialsProvider credentials(std::move(userName),
581 std::move(password));
582
583 // Payload must contain data + NULL delimiters
584 if (credentials.user().size() + credentials.password().size() + 2 >
585 secretLimit)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100586 {
Ed Tanous22db1722021-06-09 10:53:51 -0700587 BMCWEB_LOG_ERROR << "Credentials too long to handle";
588 messages::unrecognizedRequestBody(asyncResp->res);
589 return;
590 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100591
Ed Tanous22db1722021-06-09 10:53:51 -0700592 // Pack secret
593 auto secret = credentials.pack(
594 [](const auto& user, const auto& pass, auto& buff) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700595 std::copy(user.begin(), user.end(), std::back_inserter(buff));
596 buff.push_back('\0');
597 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
598 buff.push_back('\0');
599 });
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100600
Ed Tanous22db1722021-06-09 10:53:51 -0700601 // Open pipe
602 secretPipe = std::make_shared<SecurePipe>(
603 crow::connections::systemBus->get_io_context(), std::move(secret));
604 unixFd = secretPipe->fd();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100605
Ed Tanous22db1722021-06-09 10:53:51 -0700606 // Pass secret over pipe
607 secretPipe->asyncWrite(
608 [asyncResp](const boost::system::error_code& ec, std::size_t) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700609 if (ec)
610 {
611 BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
612 messages::internalError(asyncResp->res);
613 }
614 });
Ed Tanous22db1722021-06-09 10:53:51 -0700615 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100616
Ed Tanous22db1722021-06-09 10:53:51 -0700617 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800618 [asyncResp, secretPipe](const boost::system::error_code& ec,
Ed Tanous22db1722021-06-09 10:53:51 -0700619 bool success) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700620 if (ec)
621 {
622 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
623 messages::internalError(asyncResp->res);
624 }
625 else if (!success)
626 {
627 BMCWEB_LOG_ERROR << "Service responded with error";
628 messages::generalError(asyncResp->res);
629 }
Ed Tanous22db1722021-06-09 10:53:51 -0700630 },
631 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
632 "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
633 unixFd);
634}
635
636/**
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200637 * @brief Function validate parameters of insert media request.
638 *
639 */
640inline void validateParams(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
641 const std::string& service,
642 const std::string& resName,
643 InsertMediaActionParams& actionParams)
644{
645 BMCWEB_LOG_DEBUG << "Validation started";
646 // required param imageUrl must not be empty
647 if (!actionParams.imageUrl)
648 {
649 BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
650
651 messages::propertyValueFormatError(asyncResp->res, "<empty>", "Image");
652
653 return;
654 }
655
656 // optional param inserted must be true
657 if ((actionParams.inserted != std::nullopt) && !*actionParams.inserted)
658 {
659 BMCWEB_LOG_ERROR
660 << "Request action optional parameter Inserted must be true.";
661
662 messages::actionParameterNotSupported(asyncResp->res, "Inserted",
663 "InsertMedia");
664
665 return;
666 }
667
668 // optional param transferMethod must be stream
669 if ((actionParams.transferMethod != std::nullopt) &&
670 (*actionParams.transferMethod != "Stream"))
671 {
672 BMCWEB_LOG_ERROR << "Request action optional parameter "
673 "TransferMethod must be Stream.";
674
675 messages::actionParameterNotSupported(asyncResp->res, "TransferMethod",
676 "InsertMedia");
677
678 return;
679 }
680 boost::urls::result<boost::urls::url_view> url =
681 boost::urls::parse_uri(*actionParams.imageUrl);
682 if (!url)
683 {
684 messages::actionParameterValueFormatError(
685 asyncResp->res, *actionParams.imageUrl, "Image", "InsertMedia");
686 return;
687 }
688 std::optional<TransferProtocol> uriTransferProtocolType =
689 getTransferProtocolFromUri(*url);
690
691 std::optional<TransferProtocol> paramTransferProtocolType =
692 getTransferProtocolFromParam(actionParams.transferProtocolType);
693
694 // ImageUrl does not contain valid protocol type
695 if (*uriTransferProtocolType == TransferProtocol::invalid)
696 {
697 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
698 "contain specified protocol type from list: "
699 "(smb, https).";
700
701 messages::resourceAtUriInUnknownFormat(asyncResp->res, *url);
702
703 return;
704 }
705
706 // transferProtocolType should contain value from list
707 if (*paramTransferProtocolType == TransferProtocol::invalid)
708 {
709 BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
710 "must be provided with value from list: "
711 "(CIFS, HTTPS).";
712
713 messages::propertyValueNotInList(asyncResp->res,
714 *actionParams.transferProtocolType,
715 "TransferProtocolType");
716 return;
717 }
718
719 // valid transfer protocol not provided either with URI nor param
720 if ((uriTransferProtocolType == std::nullopt) &&
721 (paramTransferProtocolType == std::nullopt))
722 {
723 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
724 "contain specified protocol type or param "
725 "TransferProtocolType must be provided.";
726
727 messages::resourceAtUriInUnknownFormat(asyncResp->res, *url);
728
729 return;
730 }
731
732 // valid transfer protocol provided both with URI and param
733 if ((paramTransferProtocolType != std::nullopt) &&
734 (uriTransferProtocolType != std::nullopt))
735 {
736 // check if protocol is the same for URI and param
737 if (*paramTransferProtocolType != *uriTransferProtocolType)
738 {
739 BMCWEB_LOG_ERROR << "Request action parameter "
740 "TransferProtocolType must contain the "
741 "same protocol type as protocol type "
742 "provided with param imageUrl.";
743
744 messages::actionParameterValueTypeError(
745 asyncResp->res, *actionParams.transferProtocolType,
746 "TransferProtocolType", "InsertMedia");
747
748 return;
749 }
750 }
751
752 // validation passed, add protocol to URI if needed
753 if (uriTransferProtocolType == std::nullopt)
754 {
755 actionParams.imageUrl = getUriWithTransferProtocol(
756 *actionParams.imageUrl, *paramTransferProtocolType);
757 }
758
759 doMountVmLegacy(asyncResp, service, resName, *actionParams.imageUrl,
760 !(*actionParams.writeProtected),
761 std::move(*actionParams.userName),
762 std::move(*actionParams.password));
763}
764
765/**
Ed Tanous22db1722021-06-09 10:53:51 -0700766 * @brief Function transceives data with dbus directly.
767 *
768 * All BMC state properties will be retrieved before sending reset request.
769 */
Ed Tanous24e740a2023-02-24 12:08:58 -0800770inline void doEjectAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
771 const std::string& service, const std::string& name,
772 bool legacy)
Ed Tanous22db1722021-06-09 10:53:51 -0700773{
774
775 // Legacy mount requires parameter with image
776 if (legacy)
777 {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100778 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800779 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700780 if (ec)
781 {
782 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700783
Ed Tanous002d39b2022-05-31 08:59:27 -0700784 messages::internalError(asyncResp->res);
785 return;
786 }
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100787 },
788 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
Ed Tanous22db1722021-06-09 10:53:51 -0700789 "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200790 }
Ed Tanous22db1722021-06-09 10:53:51 -0700791 else // proxy
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200792 {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200793 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800794 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700795 if (ec)
796 {
797 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700798
Ed Tanous002d39b2022-05-31 08:59:27 -0700799 messages::internalError(asyncResp->res);
800 return;
801 }
Ed Tanous22db1722021-06-09 10:53:51 -0700802 },
803 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
804 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
805 }
806}
807
Ed Tanous96825be2022-06-03 09:43:38 -0700808inline void handleManagersVirtualMediaActionInsertPost(
809 crow::App& app, const crow::Request& req,
810 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
811 const std::string& name, const std::string& resName)
812{
813 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
814 {
815 return;
816 }
817 if (name != "bmc")
818 {
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200819 messages::resourceNotFound(asyncResp->res, "VirtualMedia.InsertMedia",
Ed Tanous96825be2022-06-03 09:43:38 -0700820 resName);
821
822 return;
823 }
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200824 std::optional<InsertMediaActionParams> actionParams =
825 InsertMediaActionParams();
Ed Tanous96825be2022-06-03 09:43:38 -0700826
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200827 // Read obligatory parameters (url of image)
Ed Tanous96825be2022-06-03 09:43:38 -0700828 if (!json_util::readJsonAction(
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200829 req, asyncResp->res, "Image", actionParams->imageUrl,
830 "WriteProtected", actionParams->writeProtected, "UserName",
831 actionParams->userName, "Password", actionParams->password,
832 "Inserted", actionParams->inserted, "TransferMethod",
833 actionParams->transferMethod, "TransferProtocolType",
834 actionParams->transferProtocolType))
Ed Tanous96825be2022-06-03 09:43:38 -0700835 {
836 return;
837 }
838
George Liu2b731192023-01-11 16:27:13 +0800839 dbus::utility::getDbusObject(
840 "/xyz/openbmc_project/VirtualMedia", {},
Ed Tanous96825be2022-06-03 09:43:38 -0700841 [asyncResp, actionParams,
George Liu2b731192023-01-11 16:27:13 +0800842 resName](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -0700843 const dbus::utility::MapperGetObject& getObjectType) mutable {
844 if (ec)
845 {
846 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
847 messages::internalError(asyncResp->res);
848
849 return;
850 }
851 std::string service = getObjectType.begin()->first;
852 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
853
854 crow::connections::systemBus->async_method_call(
855 [service, resName, actionParams,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800856 asyncResp](const boost::system::error_code& ec2,
Ed Tanous96825be2022-06-03 09:43:38 -0700857 dbus::utility::ManagedObjectType& subtree) mutable {
Ed Tanous8a592812022-06-04 09:06:59 -0700858 if (ec2)
Ed Tanous96825be2022-06-03 09:43:38 -0700859 {
860 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200861 messages::internalError(asyncResp->res);
Ed Tanous96825be2022-06-03 09:43:38 -0700862
863 return;
864 }
865
866 for (const auto& object : subtree)
867 {
Ed Tanous365a73f2023-02-24 12:16:49 -0800868 VmMode mode = parseObjectPathAndGetMode(object.first, resName);
869 if (mode == VmMode::Proxy)
Ed Tanous96825be2022-06-03 09:43:38 -0700870 {
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200871 validateParams(asyncResp, service, resName, *actionParams);
Ed Tanous96825be2022-06-03 09:43:38 -0700872
873 return;
874 }
875 }
876 BMCWEB_LOG_DEBUG << "Parent item not found";
877 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
878 },
879 service, "/xyz/openbmc_project/VirtualMedia",
880 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
George Liu2b731192023-01-11 16:27:13 +0800881 });
Ed Tanous96825be2022-06-03 09:43:38 -0700882}
883
884inline void handleManagersVirtualMediaActionEject(
885 crow::App& app, const crow::Request& req,
886 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
887 const std::string& managerName, const std::string& resName)
888{
889 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
890 {
891 return;
892 }
893 if (managerName != "bmc")
894 {
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200895 messages::resourceNotFound(asyncResp->res, "VirtualMedia.EjectMedia",
Ed Tanous96825be2022-06-03 09:43:38 -0700896 resName);
897
898 return;
899 }
900
George Liu2b731192023-01-11 16:27:13 +0800901 dbus::utility::getDbusObject(
902 "/xyz/openbmc_project/VirtualMedia", {},
Ed Tanous96825be2022-06-03 09:43:38 -0700903 [asyncResp,
George Liu2b731192023-01-11 16:27:13 +0800904 resName](const boost::system::error_code& ec2,
Ed Tanous96825be2022-06-03 09:43:38 -0700905 const dbus::utility::MapperGetObject& getObjectType) {
Ed Tanous8a592812022-06-04 09:06:59 -0700906 if (ec2)
Ed Tanous96825be2022-06-03 09:43:38 -0700907 {
Ed Tanous8a592812022-06-04 09:06:59 -0700908 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec2;
Ed Tanous96825be2022-06-03 09:43:38 -0700909 messages::internalError(asyncResp->res);
910
911 return;
912 }
913 std::string service = getObjectType.begin()->first;
914 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
915
916 crow::connections::systemBus->async_method_call(
Ed Tanous02cad962022-06-30 16:50:15 -0700917 [resName, service, asyncResp{asyncResp}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800918 const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700919 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous96825be2022-06-03 09:43:38 -0700920 if (ec)
921 {
922 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200923 messages::internalError(asyncResp->res);
Ed Tanous96825be2022-06-03 09:43:38 -0700924
925 return;
926 }
927
928 for (const auto& object : subtree)
929 {
Ed Tanous96825be2022-06-03 09:43:38 -0700930
Ed Tanous365a73f2023-02-24 12:16:49 -0800931 VmMode mode = parseObjectPathAndGetMode(object.first, resName);
932 if (mode != VmMode::Invalid)
Ed Tanous96825be2022-06-03 09:43:38 -0700933 {
Ed Tanous365a73f2023-02-24 12:16:49 -0800934 doEjectAction(asyncResp, service, resName,
935 mode == VmMode::Legacy);
Ed Tanous96825be2022-06-03 09:43:38 -0700936 }
937 }
938 BMCWEB_LOG_DEBUG << "Parent item not found";
939 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
940 },
941 service, "/xyz/openbmc_project/VirtualMedia",
942 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
George Liu2b731192023-01-11 16:27:13 +0800943 });
Ed Tanous96825be2022-06-03 09:43:38 -0700944}
945
946inline void handleManagersVirtualMediaCollectionGet(
947 crow::App& app, const crow::Request& req,
948 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
949 const std::string& name)
950{
951 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
952 {
953 return;
954 }
955 if (name != "bmc")
956 {
957 messages::resourceNotFound(asyncResp->res, "VirtualMedia", name);
958
959 return;
960 }
961
962 asyncResp->res.jsonValue["@odata.type"] =
963 "#VirtualMediaCollection.VirtualMediaCollection";
964 asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
Ed Tanousfdb20342022-06-03 09:56:52 -0700965 asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
966 "redfish", "v1", "Managers", name, "VirtualMedia");
Ed Tanous96825be2022-06-03 09:43:38 -0700967
George Liu2b731192023-01-11 16:27:13 +0800968 dbus::utility::getDbusObject(
969 "/xyz/openbmc_project/VirtualMedia", {},
970 [asyncResp, name](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -0700971 const dbus::utility::MapperGetObject& getObjectType) {
972 if (ec)
973 {
974 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
975 messages::internalError(asyncResp->res);
976
977 return;
978 }
979 std::string service = getObjectType.begin()->first;
980 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
981
982 getVmResourceList(asyncResp, service, name);
George Liu2b731192023-01-11 16:27:13 +0800983 });
Ed Tanous96825be2022-06-03 09:43:38 -0700984}
985
986inline void
987 handleVirtualMediaGet(crow::App& app, const crow::Request& req,
988 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
989 const std::string& name, const std::string& resName)
990{
991 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
992 {
993 return;
994 }
995 if (name != "bmc")
996 {
997 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
998
999 return;
1000 }
1001
George Liu2b731192023-01-11 16:27:13 +08001002 dbus::utility::getDbusObject(
1003 "/xyz/openbmc_project/VirtualMedia", {},
Ed Tanous96825be2022-06-03 09:43:38 -07001004 [asyncResp, name,
George Liu2b731192023-01-11 16:27:13 +08001005 resName](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -07001006 const dbus::utility::MapperGetObject& getObjectType) {
1007 if (ec)
1008 {
1009 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
1010 messages::internalError(asyncResp->res);
1011
1012 return;
1013 }
1014 std::string service = getObjectType.begin()->first;
1015 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1016
1017 getVmData(asyncResp, service, name, resName);
George Liu2b731192023-01-11 16:27:13 +08001018 });
Ed Tanous96825be2022-06-03 09:43:38 -07001019}
1020
Ed Tanous22db1722021-06-09 10:53:51 -07001021inline void requestNBDVirtualMediaRoutes(App& app)
1022{
George Liu0fda0f12021-11-16 10:06:17 +08001023 BMCWEB_ROUTE(
1024 app,
1025 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
Ed Tanoused398212021-06-09 17:05:54 -07001026 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous96825be2022-06-03 09:43:38 -07001027 .methods(boost::beast::http::verb::post)(std::bind_front(
1028 handleManagersVirtualMediaActionInsertPost, std::ref(app)));
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +02001029
George Liu0fda0f12021-11-16 10:06:17 +08001030 BMCWEB_ROUTE(
1031 app,
1032 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
Ed Tanoused398212021-06-09 17:05:54 -07001033 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous96825be2022-06-03 09:43:38 -07001034 .methods(boost::beast::http::verb::post)(std::bind_front(
1035 handleManagersVirtualMediaActionEject, std::ref(app)));
Ed Tanous002d39b2022-05-31 08:59:27 -07001036
Ed Tanous22db1722021-06-09 10:53:51 -07001037 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
Ed Tanoused398212021-06-09 17:05:54 -07001038 .privileges(redfish::privileges::getVirtualMediaCollection)
Ed Tanous96825be2022-06-03 09:43:38 -07001039 .methods(boost::beast::http::verb::get)(std::bind_front(
1040 handleManagersVirtualMediaCollectionGet, std::ref(app)));
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001041
Ed Tanous22db1722021-06-09 10:53:51 -07001042 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001043 .privileges(redfish::privileges::getVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -07001044 .methods(boost::beast::http::verb::get)(
Ed Tanous96825be2022-06-03 09:43:38 -07001045 std::bind_front(handleVirtualMediaGet, std::ref(app)));
Ed Tanous22db1722021-06-09 10:53:51 -07001046}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001047
1048} // namespace redfish