blob: 51380a982ae5560fc8a2f28771d266e27a9b3c04 [file] [log] [blame]
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "account_service.hpp"
19#include "app.hpp"
George Liu2b731192023-01-11 16:27:13 +080020#include "dbus_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080021#include "query.hpp"
22#include "registries/privilege_registry.hpp"
23#include "utils/json_utils.hpp"
24
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +010025#include <boost/process/async_pipe.hpp>
26#include <boost/type_traits/has_dereference.hpp>
Anna Platash9e319cf2020-11-17 10:18:31 +010027#include <boost/url/url_view.hpp>
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020028
George Liu2b731192023-01-11 16:27:13 +080029#include <array>
30#include <string_view>
31
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020032namespace redfish
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020033{
Anna Platash9e319cf2020-11-17 10:18:31 +010034/**
35 * @brief Function extracts transfer protocol name from URI.
36 */
Ed Tanous67df0732021-10-26 11:23:56 -070037inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
38{
39 boost::urls::result<boost::urls::url_view> url =
Ed Tanous079360a2022-06-29 10:05:19 -070040 boost::urls::parse_uri(imageUri);
Ed Tanous67df0732021-10-26 11:23:56 -070041 if (!url)
42 {
43 return "None";
44 }
Ed Tanous079360a2022-06-29 10:05:19 -070045 std::string_view scheme = url->scheme();
Ed Tanous67df0732021-10-26 11:23:56 -070046 if (scheme == "smb")
47 {
48 return "CIFS";
49 }
50 if (scheme == "https")
51 {
52 return "HTTPS";
53 }
54
55 return "None";
56}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020057
58/**
59 * @brief Read all known properties from VM object interfaces
60 */
Ed Tanous22db1722021-06-09 10:53:51 -070061inline void
Ed Tanous8a592812022-06-04 09:06:59 -070062 vmParseInterfaceObject(const dbus::utility::DBusInteracesMap& interfaces,
zhanghch058d1b46d2021-04-01 11:18:24 +080063 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020064{
Ed Tanous8a592812022-06-04 09:06:59 -070065 for (const auto& [interface, values] : interfaces)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020066 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080067 if (interface == "xyz.openbmc_project.VirtualMedia.MountPoint")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020068 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080069 for (const auto& [property, value] : values)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020070 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080071 if (property == "EndpointId")
72 {
73 const std::string* endpointIdValue =
74 std::get_if<std::string>(&value);
75 if (endpointIdValue == nullptr)
76 {
77 continue;
78 }
79 if (!endpointIdValue->empty())
80 {
81 // Proxy mode
82 aResp->res
83 .jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
84 *endpointIdValue;
85 aResp->res.jsonValue["TransferProtocolType"] = "OEM";
86 }
87 }
88 if (property == "ImageURL")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020089 {
Anna Platash9e319cf2020-11-17 10:18:31 +010090 const std::string* imageUrlValue =
Ed Tanous711ac7a2021-12-20 09:34:41 -080091 std::get_if<std::string>(&value);
Ed Tanous26f69762022-01-25 09:49:11 -080092 if (imageUrlValue != nullptr && !imageUrlValue->empty())
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +010093 {
Anna Platash9e319cf2020-11-17 10:18:31 +010094 std::filesystem::path filePath = *imageUrlValue;
95 if (!filePath.has_filename())
96 {
97 // this will handle https share, which not
98 // necessarily has to have filename given.
99 aResp->res.jsonValue["ImageName"] = "";
100 }
101 else
102 {
103 aResp->res.jsonValue["ImageName"] =
104 filePath.filename();
105 }
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100106
Anna Platash9e319cf2020-11-17 10:18:31 +0100107 aResp->res.jsonValue["Image"] = *imageUrlValue;
Anna Platash9e319cf2020-11-17 10:18:31 +0100108 aResp->res.jsonValue["TransferProtocolType"] =
109 getTransferProtocolTypeFromUri(*imageUrlValue);
110
Ed Tanous711ac7a2021-12-20 09:34:41 -0800111 aResp->res.jsonValue["ConnectedVia"] = "URI";
Anna Platash9e319cf2020-11-17 10:18:31 +0100112 }
113 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800114 if (property == "WriteProtected")
Anna Platash9e319cf2020-11-17 10:18:31 +0100115 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800116 const bool* writeProtectedValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800117 if (writeProtectedValue != nullptr)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200118 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100119 aResp->res.jsonValue["WriteProtected"] =
120 *writeProtectedValue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200121 }
122 }
123 }
124 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800125 if (interface == "xyz.openbmc_project.VirtualMedia.Process")
126 {
127 for (const auto& [property, value] : values)
128 {
129 if (property == "Active")
130 {
131 const bool* activeValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800132 if (activeValue == nullptr)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800133 {
134 BMCWEB_LOG_DEBUG << "Value Active not found";
135 return;
136 }
137 aResp->res.jsonValue["Inserted"] = *activeValue;
138
Ed Tanouse05aec52022-01-25 10:28:56 -0800139 if (*activeValue)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800140 {
141 aResp->res.jsonValue["ConnectedVia"] = "Applet";
142 }
143 }
144 }
145 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200146 }
147}
148
149/**
150 * @brief Fill template for Virtual Media Item.
151 */
Ed Tanous22db1722021-06-09 10:53:51 -0700152inline nlohmann::json vmItemTemplate(const std::string& name,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500153 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200154{
155 nlohmann::json item;
Ed Tanousfdb20342022-06-03 09:56:52 -0700156 item["@odata.id"] = crow::utility::urlFromPieces(
157 "redfish", "v1", "Managers", name, "VirtualMedia", resName);
Ed Tanous22db1722021-06-09 10:53:51 -0700158
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100159 item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200160 item["Name"] = "Virtual Removable Media";
161 item["Id"] = resName;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200162 item["WriteProtected"] = true;
Ed Tanous613dabe2022-07-09 11:17:36 -0700163 item["MediaTypes"] = nlohmann::json::array_t({"CD", "USBStick"});
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200164 item["TransferMethod"] = "Stream";
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100165 item["Oem"]["OpenBMC"]["@odata.type"] =
166 "#OemVirtualMedia.v1_0_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200167
168 return item;
169}
170
171/**
172 * @brief Fills collection data
173 */
Ed Tanous22db1722021-06-09 10:53:51 -0700174inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500175 const std::string& service,
176 const std::string& name)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200177{
178 BMCWEB_LOG_DEBUG << "Get available Virtual Media resources.";
179 crow::connections::systemBus->async_method_call(
Ed Tanous02cad962022-06-30 16:50:15 -0700180 [name, aResp{std::move(aResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800181 const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700182 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700183 if (ec)
184 {
185 BMCWEB_LOG_DEBUG << "DBUS response error";
186 return;
187 }
188 nlohmann::json& members = aResp->res.jsonValue["Members"];
189 members = nlohmann::json::array();
190
191 for (const auto& object : subtree)
192 {
193 nlohmann::json item;
194 std::string path = object.first.filename();
195 if (path.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200196 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700197 continue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200198 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200199
Ed Tanousfdb20342022-06-03 09:56:52 -0700200 item["@odata.id"] = crow::utility::urlFromPieces(
201 "redfish", "v1", "Managers", name, "VirtualMedia", path);
Ed Tanous002d39b2022-05-31 08:59:27 -0700202 members.emplace_back(std::move(item));
203 }
204 aResp->res.jsonValue["Members@odata.count"] = members.size();
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200205 },
206 service, "/xyz/openbmc_project/VirtualMedia",
207 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
208}
209
210/**
211 * @brief Fills data for specific resource
212 */
Ed Tanous22db1722021-06-09 10:53:51 -0700213inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500214 const std::string& service, const std::string& name,
215 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200216{
217 BMCWEB_LOG_DEBUG << "Get Virtual Media resource data.";
218
219 crow::connections::systemBus->async_method_call(
Ed Tanous914e2d52022-01-07 11:38:34 -0800220 [resName, name,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800221 aResp](const boost::system::error_code& ec,
Ed Tanous914e2d52022-01-07 11:38:34 -0800222 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700223 if (ec)
224 {
225 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200226
Ed Tanous002d39b2022-05-31 08:59:27 -0700227 return;
228 }
229
230 for (const auto& item : subtree)
231 {
232 std::string thispath = item.first.filename();
233 if (thispath.empty())
234 {
235 continue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200236 }
237
Ed Tanous002d39b2022-05-31 08:59:27 -0700238 if (thispath != resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200239 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700240 continue;
241 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200242
Ed Tanous002d39b2022-05-31 08:59:27 -0700243 // "Legacy"/"Proxy"
244 auto mode = item.first.parent_path();
245 // "VirtualMedia"
246 auto type = mode.parent_path();
247 if (mode.filename().empty() || type.filename().empty())
248 {
249 continue;
250 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200251
Ed Tanous002d39b2022-05-31 08:59:27 -0700252 if (type.filename() != "VirtualMedia")
253 {
254 continue;
255 }
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200256
Ed Tanous002d39b2022-05-31 08:59:27 -0700257 aResp->res.jsonValue = vmItemTemplate(name, resName);
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200258
Ed Tanous002d39b2022-05-31 08:59:27 -0700259 // Check if dbus path is Legacy type
260 if (mode.filename() == "Legacy")
261 {
262 aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
Ed Tanousfdb20342022-06-03 09:56:52 -0700263 ["target"] = crow::utility::urlFromPieces(
264 "redfish", "v1", "Managers", name, "VirtualMedia", resName,
265 "Actions", "VirtualMedia.InsertMedia");
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200266 }
267
Ed Tanous002d39b2022-05-31 08:59:27 -0700268 vmParseInterfaceObject(item.second, aResp);
269
270 aResp->res
271 .jsonValue["Actions"]["#VirtualMedia.EjectMedia"]["target"] =
Ed Tanousfdb20342022-06-03 09:56:52 -0700272 crow::utility::urlFromPieces("redfish", "v1", "Managers", name,
273 "VirtualMedia", resName, "Actions",
274 "VirtualMedia.EjectMedia");
Ed Tanous002d39b2022-05-31 08:59:27 -0700275 return;
276 }
277
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +0800278 messages::resourceNotFound(aResp->res, "VirtualMedia", resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200279 },
280 service, "/xyz/openbmc_project/VirtualMedia",
281 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
282}
283
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200284/**
Ed Tanous22db1722021-06-09 10:53:51 -0700285 * @brief Transfer protocols supported for InsertMedia action.
286 *
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200287 */
Ed Tanous22db1722021-06-09 10:53:51 -0700288enum class TransferProtocol
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200289{
Ed Tanous22db1722021-06-09 10:53:51 -0700290 https,
291 smb,
292 invalid
293};
294
295/**
296 * @brief Function extracts transfer protocol type from URI.
297 *
298 */
Ed Tanous67df0732021-10-26 11:23:56 -0700299inline std::optional<TransferProtocol>
Ed Tanousace85d62021-10-26 12:45:59 -0700300 getTransferProtocolFromUri(const boost::urls::url_view& imageUri)
Ed Tanous67df0732021-10-26 11:23:56 -0700301{
Ed Tanous079360a2022-06-29 10:05:19 -0700302 std::string_view scheme = imageUri.scheme();
Ed Tanous67df0732021-10-26 11:23:56 -0700303 if (scheme == "smb")
304 {
305 return TransferProtocol::smb;
306 }
307 if (scheme == "https")
308 {
309 return TransferProtocol::https;
310 }
311 if (!scheme.empty())
312 {
313 return TransferProtocol::invalid;
314 }
315
316 return {};
317}
Ed Tanous22db1722021-06-09 10:53:51 -0700318
319/**
320 * @brief Function convert transfer protocol from string param.
321 *
322 */
323inline std::optional<TransferProtocol> getTransferProtocolFromParam(
324 const std::optional<std::string>& transferProtocolType)
325{
326 if (transferProtocolType == std::nullopt)
Agata Olenderc6f4e012020-03-11 15:19:07 +0100327 {
Ed Tanous22db1722021-06-09 10:53:51 -0700328 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100329 }
330
Ed Tanous22db1722021-06-09 10:53:51 -0700331 if (*transferProtocolType == "CIFS")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200332 {
Ed Tanous22db1722021-06-09 10:53:51 -0700333 return TransferProtocol::smb;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200334 }
335
Ed Tanous22db1722021-06-09 10:53:51 -0700336 if (*transferProtocolType == "HTTPS")
337 {
338 return TransferProtocol::https;
339 }
340
341 return TransferProtocol::invalid;
342}
343
344/**
345 * @brief Function extends URI with transfer protocol type.
346 *
347 */
348inline std::string
349 getUriWithTransferProtocol(const std::string& imageUri,
350 const TransferProtocol& transferProtocol)
351{
352 if (transferProtocol == TransferProtocol::smb)
353 {
354 return "smb://" + imageUri;
355 }
356
357 if (transferProtocol == TransferProtocol::https)
358 {
359 return "https://" + imageUri;
360 }
361
362 return imageUri;
363}
364
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200365struct InsertMediaActionParams
366{
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200367 std::optional<std::string> imageUrl;
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200368 std::optional<std::string> userName;
369 std::optional<std::string> password;
370 std::optional<std::string> transferMethod;
371 std::optional<std::string> transferProtocolType;
372 std::optional<bool> writeProtected = true;
373 std::optional<bool> inserted;
374};
375
Ed Tanous22db1722021-06-09 10:53:51 -0700376template <typename T>
377static void secureCleanup(T& value)
378{
Ed Tanous4ecc6182022-01-07 09:36:26 -0800379 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
Ed Tanous22db1722021-06-09 10:53:51 -0700380 auto raw = const_cast<typename T::value_type*>(value.data());
381 explicit_bzero(raw, value.size() * sizeof(*raw));
382}
383
384class Credentials
385{
386 public:
387 Credentials(std::string&& user, std::string&& password) :
388 userBuf(std::move(user)), passBuf(std::move(password))
389 {}
390
391 ~Credentials()
392 {
393 secureCleanup(userBuf);
394 secureCleanup(passBuf);
395 }
396
397 const std::string& user()
398 {
399 return userBuf;
400 }
401
402 const std::string& password()
403 {
404 return passBuf;
405 }
406
407 Credentials() = delete;
408 Credentials(const Credentials&) = delete;
409 Credentials& operator=(const Credentials&) = delete;
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800410 Credentials(Credentials&&) = delete;
411 Credentials& operator=(Credentials&&) = delete;
Ed Tanous22db1722021-06-09 10:53:51 -0700412
413 private:
414 std::string userBuf;
415 std::string passBuf;
416};
417
418class CredentialsProvider
419{
420 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500421 template <typename T>
Ed Tanous22db1722021-06-09 10:53:51 -0700422 struct Deleter
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100423 {
Ed Tanous22db1722021-06-09 10:53:51 -0700424 void operator()(T* buff) const
425 {
426 if (buff)
427 {
428 secureCleanup(*buff);
429 delete buff;
430 }
431 }
432 };
433
434 using Buffer = std::vector<char>;
435 using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
436 // Using explicit definition instead of std::function to avoid implicit
437 // conversions eg. stack copy instead of reference
438 using FormatterFunc = void(const std::string& username,
439 const std::string& password, Buffer& dest);
440
441 CredentialsProvider(std::string&& user, std::string&& password) :
442 credentials(std::move(user), std::move(password))
443 {}
444
445 const std::string& user()
446 {
447 return credentials.user();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100448 }
449
Ed Tanous22db1722021-06-09 10:53:51 -0700450 const std::string& password()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100451 {
Ed Tanous22db1722021-06-09 10:53:51 -0700452 return credentials.password();
453 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100454
Ed Tanous1917ee92022-06-30 22:30:50 -0700455 SecureBuffer pack(FormatterFunc* formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100456 {
Ed Tanous22db1722021-06-09 10:53:51 -0700457 SecureBuffer packed{new Buffer{}};
Ed Tanouse662eae2022-01-25 10:39:19 -0800458 if (formatter != nullptr)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100459 {
Ed Tanous22db1722021-06-09 10:53:51 -0700460 formatter(credentials.user(), credentials.password(), *packed);
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100461 }
462
Ed Tanous22db1722021-06-09 10:53:51 -0700463 return packed;
464 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100465
Ed Tanous22db1722021-06-09 10:53:51 -0700466 private:
467 Credentials credentials;
468};
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100469
Ed Tanous22db1722021-06-09 10:53:51 -0700470// Wrapper for boost::async_pipe ensuring proper pipe cleanup
471template <typename Buffer>
472class Pipe
473{
474 public:
475 using unix_fd = sdbusplus::message::unix_fd;
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100476
Ed Tanous8a592812022-06-04 09:06:59 -0700477 Pipe(boost::asio::io_context& io, Buffer&& bufferIn) :
478 impl(io), buffer{std::move(bufferIn)}
Ed Tanous22db1722021-06-09 10:53:51 -0700479 {}
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100480
Ed Tanous22db1722021-06-09 10:53:51 -0700481 ~Pipe()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100482 {
Ed Tanous22db1722021-06-09 10:53:51 -0700483 // Named pipe needs to be explicitly removed
484 impl.close();
485 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100486
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800487 Pipe(const Pipe&) = delete;
488 Pipe(Pipe&&) = delete;
489 Pipe& operator=(const Pipe&) = delete;
490 Pipe& operator=(Pipe&&) = delete;
491
Ed Tanous22db1722021-06-09 10:53:51 -0700492 unix_fd fd()
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200493 {
Ed Tanous22db1722021-06-09 10:53:51 -0700494 return unix_fd{impl.native_source()};
495 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100496
Ed Tanous22db1722021-06-09 10:53:51 -0700497 template <typename WriteHandler>
498 void asyncWrite(WriteHandler&& handler)
499 {
500 impl.async_write_some(data(), std::forward<WriteHandler>(handler));
501 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100502
Ed Tanous22db1722021-06-09 10:53:51 -0700503 private:
504 // Specialization for pointer types
505 template <typename B = Buffer>
506 typename std::enable_if<boost::has_dereference<B>::value,
507 boost::asio::const_buffer>::type
508 data()
509 {
510 return boost::asio::buffer(*buffer);
511 }
512
513 template <typename B = Buffer>
514 typename std::enable_if<!boost::has_dereference<B>::value,
515 boost::asio::const_buffer>::type
516 data()
517 {
518 return boost::asio::buffer(buffer);
519 }
520
521 const std::string name;
522 boost::process::async_pipe impl;
523 Buffer buffer;
524};
525
526/**
527 * @brief Function transceives data with dbus directly.
528 *
529 * All BMC state properties will be retrieved before sending reset request.
530 */
531inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
532 const std::string& service, const std::string& name,
533 const std::string& imageUrl, const bool rw,
534 std::string&& userName, std::string&& password)
535{
536 using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
537 constexpr const size_t secretLimit = 1024;
538
539 std::shared_ptr<SecurePipe> secretPipe;
Ed Tanous168e20c2021-12-13 14:39:53 -0800540 dbus::utility::DbusVariantType unixFd = -1;
Ed Tanous22db1722021-06-09 10:53:51 -0700541
542 if (!userName.empty() || !password.empty())
543 {
544 // Encapsulate in safe buffer
545 CredentialsProvider credentials(std::move(userName),
546 std::move(password));
547
548 // Payload must contain data + NULL delimiters
549 if (credentials.user().size() + credentials.password().size() + 2 >
550 secretLimit)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100551 {
Ed Tanous22db1722021-06-09 10:53:51 -0700552 BMCWEB_LOG_ERROR << "Credentials too long to handle";
553 messages::unrecognizedRequestBody(asyncResp->res);
554 return;
555 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100556
Ed Tanous22db1722021-06-09 10:53:51 -0700557 // Pack secret
558 auto secret = credentials.pack(
559 [](const auto& user, const auto& pass, auto& buff) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700560 std::copy(user.begin(), user.end(), std::back_inserter(buff));
561 buff.push_back('\0');
562 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
563 buff.push_back('\0');
564 });
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100565
Ed Tanous22db1722021-06-09 10:53:51 -0700566 // Open pipe
567 secretPipe = std::make_shared<SecurePipe>(
568 crow::connections::systemBus->get_io_context(), std::move(secret));
569 unixFd = secretPipe->fd();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100570
Ed Tanous22db1722021-06-09 10:53:51 -0700571 // Pass secret over pipe
572 secretPipe->asyncWrite(
573 [asyncResp](const boost::system::error_code& ec, std::size_t) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700574 if (ec)
575 {
576 BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
577 messages::internalError(asyncResp->res);
578 }
579 });
Ed Tanous22db1722021-06-09 10:53:51 -0700580 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100581
Ed Tanous22db1722021-06-09 10:53:51 -0700582 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800583 [asyncResp, secretPipe](const boost::system::error_code& ec,
Ed Tanous22db1722021-06-09 10:53:51 -0700584 bool success) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700585 if (ec)
586 {
587 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
588 messages::internalError(asyncResp->res);
589 }
590 else if (!success)
591 {
592 BMCWEB_LOG_ERROR << "Service responded with error";
593 messages::generalError(asyncResp->res);
594 }
Ed Tanous22db1722021-06-09 10:53:51 -0700595 },
596 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
597 "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
598 unixFd);
599}
600
601/**
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200602 * @brief Function validate parameters of insert media request.
603 *
604 */
605inline void validateParams(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
606 const std::string& service,
607 const std::string& resName,
608 InsertMediaActionParams& actionParams)
609{
610 BMCWEB_LOG_DEBUG << "Validation started";
611 // required param imageUrl must not be empty
612 if (!actionParams.imageUrl)
613 {
614 BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
615
616 messages::propertyValueFormatError(asyncResp->res, "<empty>", "Image");
617
618 return;
619 }
620
621 // optional param inserted must be true
622 if ((actionParams.inserted != std::nullopt) && !*actionParams.inserted)
623 {
624 BMCWEB_LOG_ERROR
625 << "Request action optional parameter Inserted must be true.";
626
627 messages::actionParameterNotSupported(asyncResp->res, "Inserted",
628 "InsertMedia");
629
630 return;
631 }
632
633 // optional param transferMethod must be stream
634 if ((actionParams.transferMethod != std::nullopt) &&
635 (*actionParams.transferMethod != "Stream"))
636 {
637 BMCWEB_LOG_ERROR << "Request action optional parameter "
638 "TransferMethod must be Stream.";
639
640 messages::actionParameterNotSupported(asyncResp->res, "TransferMethod",
641 "InsertMedia");
642
643 return;
644 }
645 boost::urls::result<boost::urls::url_view> url =
646 boost::urls::parse_uri(*actionParams.imageUrl);
647 if (!url)
648 {
649 messages::actionParameterValueFormatError(
650 asyncResp->res, *actionParams.imageUrl, "Image", "InsertMedia");
651 return;
652 }
653 std::optional<TransferProtocol> uriTransferProtocolType =
654 getTransferProtocolFromUri(*url);
655
656 std::optional<TransferProtocol> paramTransferProtocolType =
657 getTransferProtocolFromParam(actionParams.transferProtocolType);
658
659 // ImageUrl does not contain valid protocol type
660 if (*uriTransferProtocolType == TransferProtocol::invalid)
661 {
662 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
663 "contain specified protocol type from list: "
664 "(smb, https).";
665
666 messages::resourceAtUriInUnknownFormat(asyncResp->res, *url);
667
668 return;
669 }
670
671 // transferProtocolType should contain value from list
672 if (*paramTransferProtocolType == TransferProtocol::invalid)
673 {
674 BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
675 "must be provided with value from list: "
676 "(CIFS, HTTPS).";
677
678 messages::propertyValueNotInList(asyncResp->res,
679 *actionParams.transferProtocolType,
680 "TransferProtocolType");
681 return;
682 }
683
684 // valid transfer protocol not provided either with URI nor param
685 if ((uriTransferProtocolType == std::nullopt) &&
686 (paramTransferProtocolType == std::nullopt))
687 {
688 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
689 "contain specified protocol type or param "
690 "TransferProtocolType must be provided.";
691
692 messages::resourceAtUriInUnknownFormat(asyncResp->res, *url);
693
694 return;
695 }
696
697 // valid transfer protocol provided both with URI and param
698 if ((paramTransferProtocolType != std::nullopt) &&
699 (uriTransferProtocolType != std::nullopt))
700 {
701 // check if protocol is the same for URI and param
702 if (*paramTransferProtocolType != *uriTransferProtocolType)
703 {
704 BMCWEB_LOG_ERROR << "Request action parameter "
705 "TransferProtocolType must contain the "
706 "same protocol type as protocol type "
707 "provided with param imageUrl.";
708
709 messages::actionParameterValueTypeError(
710 asyncResp->res, *actionParams.transferProtocolType,
711 "TransferProtocolType", "InsertMedia");
712
713 return;
714 }
715 }
716
717 // validation passed, add protocol to URI if needed
718 if (uriTransferProtocolType == std::nullopt)
719 {
720 actionParams.imageUrl = getUriWithTransferProtocol(
721 *actionParams.imageUrl, *paramTransferProtocolType);
722 }
723
724 doMountVmLegacy(asyncResp, service, resName, *actionParams.imageUrl,
725 !(*actionParams.writeProtected),
726 std::move(*actionParams.userName),
727 std::move(*actionParams.password));
728}
729
730/**
Ed Tanous22db1722021-06-09 10:53:51 -0700731 * @brief Function transceives data with dbus directly.
732 *
733 * All BMC state properties will be retrieved before sending reset request.
734 */
Ed Tanous24e740a2023-02-24 12:08:58 -0800735inline void doEjectAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
736 const std::string& service, const std::string& name,
737 bool legacy)
Ed Tanous22db1722021-06-09 10:53:51 -0700738{
739
740 // Legacy mount requires parameter with image
741 if (legacy)
742 {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100743 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800744 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700745 if (ec)
746 {
747 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700748
Ed Tanous002d39b2022-05-31 08:59:27 -0700749 messages::internalError(asyncResp->res);
750 return;
751 }
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100752 },
753 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
Ed Tanous22db1722021-06-09 10:53:51 -0700754 "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200755 }
Ed Tanous22db1722021-06-09 10:53:51 -0700756 else // proxy
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200757 {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200758 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800759 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700760 if (ec)
761 {
762 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700763
Ed Tanous002d39b2022-05-31 08:59:27 -0700764 messages::internalError(asyncResp->res);
765 return;
766 }
Ed Tanous22db1722021-06-09 10:53:51 -0700767 },
768 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
769 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
770 }
771}
772
Ed Tanous96825be2022-06-03 09:43:38 -0700773inline void handleManagersVirtualMediaActionInsertPost(
774 crow::App& app, const crow::Request& req,
775 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
776 const std::string& name, const std::string& resName)
777{
778 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
779 {
780 return;
781 }
782 if (name != "bmc")
783 {
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200784 messages::resourceNotFound(asyncResp->res, "VirtualMedia.InsertMedia",
Ed Tanous96825be2022-06-03 09:43:38 -0700785 resName);
786
787 return;
788 }
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200789 std::optional<InsertMediaActionParams> actionParams =
790 InsertMediaActionParams();
Ed Tanous96825be2022-06-03 09:43:38 -0700791
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200792 // Read obligatory parameters (url of image)
Ed Tanous96825be2022-06-03 09:43:38 -0700793 if (!json_util::readJsonAction(
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200794 req, asyncResp->res, "Image", actionParams->imageUrl,
795 "WriteProtected", actionParams->writeProtected, "UserName",
796 actionParams->userName, "Password", actionParams->password,
797 "Inserted", actionParams->inserted, "TransferMethod",
798 actionParams->transferMethod, "TransferProtocolType",
799 actionParams->transferProtocolType))
Ed Tanous96825be2022-06-03 09:43:38 -0700800 {
801 return;
802 }
803
George Liu2b731192023-01-11 16:27:13 +0800804 dbus::utility::getDbusObject(
805 "/xyz/openbmc_project/VirtualMedia", {},
Ed Tanous96825be2022-06-03 09:43:38 -0700806 [asyncResp, actionParams,
George Liu2b731192023-01-11 16:27:13 +0800807 resName](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -0700808 const dbus::utility::MapperGetObject& getObjectType) mutable {
809 if (ec)
810 {
811 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
812 messages::internalError(asyncResp->res);
813
814 return;
815 }
816 std::string service = getObjectType.begin()->first;
817 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
818
819 crow::connections::systemBus->async_method_call(
820 [service, resName, actionParams,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800821 asyncResp](const boost::system::error_code& ec2,
Ed Tanous96825be2022-06-03 09:43:38 -0700822 dbus::utility::ManagedObjectType& subtree) mutable {
Ed Tanous8a592812022-06-04 09:06:59 -0700823 if (ec2)
Ed Tanous96825be2022-06-03 09:43:38 -0700824 {
825 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200826 messages::internalError(asyncResp->res);
Ed Tanous96825be2022-06-03 09:43:38 -0700827
828 return;
829 }
830
831 for (const auto& object : subtree)
832 {
833 const std::string& path =
834 static_cast<const std::string&>(object.first);
835
836 std::size_t lastIndex = path.rfind('/');
837 if (lastIndex == std::string::npos)
838 {
839 continue;
840 }
841
842 lastIndex += 1;
843
844 if (path.substr(lastIndex) == resName)
845 {
846 lastIndex = path.rfind("Proxy");
847 if (lastIndex != std::string::npos)
848 {
849 // Not possible in proxy mode
850 BMCWEB_LOG_DEBUG << "InsertMedia not "
851 "allowed in proxy mode";
852 messages::resourceNotFound(asyncResp->res,
853 "VirtualMedia.InsertMedia",
854 resName);
855
856 return;
857 }
858
859 lastIndex = path.rfind("Legacy");
860 if (lastIndex == std::string::npos)
861 {
862 continue;
863 }
864
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200865 if (!actionParams)
866 {
867 return;
868 }
869
870 validateParams(asyncResp, service, resName, *actionParams);
Ed Tanous96825be2022-06-03 09:43:38 -0700871
872 return;
873 }
874 }
875 BMCWEB_LOG_DEBUG << "Parent item not found";
876 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
877 },
878 service, "/xyz/openbmc_project/VirtualMedia",
879 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
George Liu2b731192023-01-11 16:27:13 +0800880 });
Ed Tanous96825be2022-06-03 09:43:38 -0700881}
882
883inline void handleManagersVirtualMediaActionEject(
884 crow::App& app, const crow::Request& req,
885 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
886 const std::string& managerName, const std::string& resName)
887{
888 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
889 {
890 return;
891 }
892 if (managerName != "bmc")
893 {
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200894 messages::resourceNotFound(asyncResp->res, "VirtualMedia.EjectMedia",
Ed Tanous96825be2022-06-03 09:43:38 -0700895 resName);
896
897 return;
898 }
899
George Liu2b731192023-01-11 16:27:13 +0800900 dbus::utility::getDbusObject(
901 "/xyz/openbmc_project/VirtualMedia", {},
Ed Tanous96825be2022-06-03 09:43:38 -0700902 [asyncResp,
George Liu2b731192023-01-11 16:27:13 +0800903 resName](const boost::system::error_code& ec2,
Ed Tanous96825be2022-06-03 09:43:38 -0700904 const dbus::utility::MapperGetObject& getObjectType) {
Ed Tanous8a592812022-06-04 09:06:59 -0700905 if (ec2)
Ed Tanous96825be2022-06-03 09:43:38 -0700906 {
Ed Tanous8a592812022-06-04 09:06:59 -0700907 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec2;
Ed Tanous96825be2022-06-03 09:43:38 -0700908 messages::internalError(asyncResp->res);
909
910 return;
911 }
912 std::string service = getObjectType.begin()->first;
913 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
914
915 crow::connections::systemBus->async_method_call(
Ed Tanous02cad962022-06-30 16:50:15 -0700916 [resName, service, asyncResp{asyncResp}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800917 const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700918 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous96825be2022-06-03 09:43:38 -0700919 if (ec)
920 {
921 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200922 messages::internalError(asyncResp->res);
Ed Tanous96825be2022-06-03 09:43:38 -0700923
924 return;
925 }
926
927 for (const auto& object : subtree)
928 {
929 const std::string& path =
930 static_cast<const std::string&>(object.first);
931
932 std::size_t lastIndex = path.rfind('/');
933 if (lastIndex == std::string::npos)
934 {
935 continue;
936 }
937
938 lastIndex += 1;
939
940 if (path.substr(lastIndex) == resName)
941 {
942 lastIndex = path.rfind("Proxy");
943 if (lastIndex != std::string::npos)
944 {
945 // Proxy mode
Ed Tanous24e740a2023-02-24 12:08:58 -0800946 doEjectAction(asyncResp, service, resName, false);
Ed Tanous96825be2022-06-03 09:43:38 -0700947 }
948
949 lastIndex = path.rfind("Legacy");
950 if (lastIndex != std::string::npos)
951 {
952 // Legacy mode
Ed Tanous24e740a2023-02-24 12:08:58 -0800953 doEjectAction(asyncResp, service, resName, true);
Ed Tanous96825be2022-06-03 09:43:38 -0700954 }
955
956 return;
957 }
958 }
959 BMCWEB_LOG_DEBUG << "Parent item not found";
960 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
961 },
962 service, "/xyz/openbmc_project/VirtualMedia",
963 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
George Liu2b731192023-01-11 16:27:13 +0800964 });
Ed Tanous96825be2022-06-03 09:43:38 -0700965}
966
967inline void handleManagersVirtualMediaCollectionGet(
968 crow::App& app, const crow::Request& req,
969 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
970 const std::string& name)
971{
972 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
973 {
974 return;
975 }
976 if (name != "bmc")
977 {
978 messages::resourceNotFound(asyncResp->res, "VirtualMedia", name);
979
980 return;
981 }
982
983 asyncResp->res.jsonValue["@odata.type"] =
984 "#VirtualMediaCollection.VirtualMediaCollection";
985 asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
Ed Tanousfdb20342022-06-03 09:56:52 -0700986 asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
987 "redfish", "v1", "Managers", name, "VirtualMedia");
Ed Tanous96825be2022-06-03 09:43:38 -0700988
George Liu2b731192023-01-11 16:27:13 +0800989 dbus::utility::getDbusObject(
990 "/xyz/openbmc_project/VirtualMedia", {},
991 [asyncResp, name](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -0700992 const dbus::utility::MapperGetObject& getObjectType) {
993 if (ec)
994 {
995 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
996 messages::internalError(asyncResp->res);
997
998 return;
999 }
1000 std::string service = getObjectType.begin()->first;
1001 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1002
1003 getVmResourceList(asyncResp, service, name);
George Liu2b731192023-01-11 16:27:13 +08001004 });
Ed Tanous96825be2022-06-03 09:43:38 -07001005}
1006
1007inline void
1008 handleVirtualMediaGet(crow::App& app, const crow::Request& req,
1009 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1010 const std::string& name, const std::string& resName)
1011{
1012 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1013 {
1014 return;
1015 }
1016 if (name != "bmc")
1017 {
1018 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
1019
1020 return;
1021 }
1022
George Liu2b731192023-01-11 16:27:13 +08001023 dbus::utility::getDbusObject(
1024 "/xyz/openbmc_project/VirtualMedia", {},
Ed Tanous96825be2022-06-03 09:43:38 -07001025 [asyncResp, name,
George Liu2b731192023-01-11 16:27:13 +08001026 resName](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -07001027 const dbus::utility::MapperGetObject& getObjectType) {
1028 if (ec)
1029 {
1030 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
1031 messages::internalError(asyncResp->res);
1032
1033 return;
1034 }
1035 std::string service = getObjectType.begin()->first;
1036 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1037
1038 getVmData(asyncResp, service, name, resName);
George Liu2b731192023-01-11 16:27:13 +08001039 });
Ed Tanous96825be2022-06-03 09:43:38 -07001040}
1041
Ed Tanous22db1722021-06-09 10:53:51 -07001042inline void requestNBDVirtualMediaRoutes(App& app)
1043{
George Liu0fda0f12021-11-16 10:06:17 +08001044 BMCWEB_ROUTE(
1045 app,
1046 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
Ed Tanoused398212021-06-09 17:05:54 -07001047 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous96825be2022-06-03 09:43:38 -07001048 .methods(boost::beast::http::verb::post)(std::bind_front(
1049 handleManagersVirtualMediaActionInsertPost, std::ref(app)));
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +02001050
George Liu0fda0f12021-11-16 10:06:17 +08001051 BMCWEB_ROUTE(
1052 app,
1053 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
Ed Tanoused398212021-06-09 17:05:54 -07001054 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous96825be2022-06-03 09:43:38 -07001055 .methods(boost::beast::http::verb::post)(std::bind_front(
1056 handleManagersVirtualMediaActionEject, std::ref(app)));
Ed Tanous002d39b2022-05-31 08:59:27 -07001057
Ed Tanous22db1722021-06-09 10:53:51 -07001058 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
Ed Tanoused398212021-06-09 17:05:54 -07001059 .privileges(redfish::privileges::getVirtualMediaCollection)
Ed Tanous96825be2022-06-03 09:43:38 -07001060 .methods(boost::beast::http::verb::get)(std::bind_front(
1061 handleManagersVirtualMediaCollectionGet, std::ref(app)));
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001062
Ed Tanous22db1722021-06-09 10:53:51 -07001063 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001064 .privileges(redfish::privileges::getVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -07001065 .methods(boost::beast::http::verb::get)(
Ed Tanous96825be2022-06-03 09:43:38 -07001066 std::bind_front(handleVirtualMediaGet, std::ref(app)));
Ed Tanous22db1722021-06-09 10:53:51 -07001067}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001068
1069} // namespace redfish