blob: 31bc7b682c940c60487c39525c1d6ab323e31b45 [file] [log] [blame]
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Ed Tanousb9d36b42022-02-26 21:42:46 -080018#include <account_service.hpp>
John Edward Broadbent7e860f12021-04-08 15:57:16 -070019#include <app.hpp>
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +010020#include <boost/process/async_pipe.hpp>
21#include <boost/type_traits/has_dereference.hpp>
Anna Platash9e319cf2020-11-17 10:18:31 +010022#include <boost/url/url_view.hpp>
Ed Tanous45ca1b82022-03-25 13:07:27 -070023#include <query.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070024#include <registries/privilege_registry.hpp>
Ed Tanousb9d36b42022-02-26 21:42:46 -080025#include <utils/json_utils.hpp>
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020026
27namespace redfish
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020028{
Anna Platash9e319cf2020-11-17 10:18:31 +010029/**
30 * @brief Function extracts transfer protocol name from URI.
31 */
Ed Tanous67df0732021-10-26 11:23:56 -070032inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
33{
34 boost::urls::result<boost::urls::url_view> url =
35 boost::urls::parse_uri(boost::string_view(imageUri));
36 if (!url)
37 {
38 return "None";
39 }
40 boost::string_view scheme = url->scheme();
41 if (scheme == "smb")
42 {
43 return "CIFS";
44 }
45 if (scheme == "https")
46 {
47 return "HTTPS";
48 }
49
50 return "None";
51}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020052
53/**
54 * @brief Read all known properties from VM object interfaces
55 */
Ed Tanous22db1722021-06-09 10:53:51 -070056inline void
Ed Tanous711ac7a2021-12-20 09:34:41 -080057 vmParseInterfaceObject(const dbus::utility::DBusInteracesMap& interface,
zhanghch058d1b46d2021-04-01 11:18:24 +080058 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020059{
Ed Tanous711ac7a2021-12-20 09:34:41 -080060 for (const auto& [interface, values] : interface)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020061 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080062 if (interface == "xyz.openbmc_project.VirtualMedia.MountPoint")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020063 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080064 for (const auto& [property, value] : values)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020065 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080066 if (property == "EndpointId")
67 {
68 const std::string* endpointIdValue =
69 std::get_if<std::string>(&value);
70 if (endpointIdValue == nullptr)
71 {
72 continue;
73 }
74 if (!endpointIdValue->empty())
75 {
76 // Proxy mode
77 aResp->res
78 .jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
79 *endpointIdValue;
80 aResp->res.jsonValue["TransferProtocolType"] = "OEM";
81 }
82 }
83 if (property == "ImageURL")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020084 {
Anna Platash9e319cf2020-11-17 10:18:31 +010085 const std::string* imageUrlValue =
Ed Tanous711ac7a2021-12-20 09:34:41 -080086 std::get_if<std::string>(&value);
Ed Tanous26f69762022-01-25 09:49:11 -080087 if (imageUrlValue != nullptr && !imageUrlValue->empty())
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +010088 {
Anna Platash9e319cf2020-11-17 10:18:31 +010089 std::filesystem::path filePath = *imageUrlValue;
90 if (!filePath.has_filename())
91 {
92 // this will handle https share, which not
93 // necessarily has to have filename given.
94 aResp->res.jsonValue["ImageName"] = "";
95 }
96 else
97 {
98 aResp->res.jsonValue["ImageName"] =
99 filePath.filename();
100 }
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100101
Anna Platash9e319cf2020-11-17 10:18:31 +0100102 aResp->res.jsonValue["Image"] = *imageUrlValue;
Anna Platash9e319cf2020-11-17 10:18:31 +0100103 aResp->res.jsonValue["TransferProtocolType"] =
104 getTransferProtocolTypeFromUri(*imageUrlValue);
105
Ed Tanous711ac7a2021-12-20 09:34:41 -0800106 aResp->res.jsonValue["ConnectedVia"] = "URI";
Anna Platash9e319cf2020-11-17 10:18:31 +0100107 }
108 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800109 if (property == "WriteProtected")
Anna Platash9e319cf2020-11-17 10:18:31 +0100110 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800111 const bool* writeProtectedValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800112 if (writeProtectedValue != nullptr)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200113 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100114 aResp->res.jsonValue["WriteProtected"] =
115 *writeProtectedValue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200116 }
117 }
118 }
119 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800120 if (interface == "xyz.openbmc_project.VirtualMedia.Process")
121 {
122 for (const auto& [property, value] : values)
123 {
124 if (property == "Active")
125 {
126 const bool* activeValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800127 if (activeValue == nullptr)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800128 {
129 BMCWEB_LOG_DEBUG << "Value Active not found";
130 return;
131 }
132 aResp->res.jsonValue["Inserted"] = *activeValue;
133
Ed Tanouse05aec52022-01-25 10:28:56 -0800134 if (*activeValue)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800135 {
136 aResp->res.jsonValue["ConnectedVia"] = "Applet";
137 }
138 }
139 }
140 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200141 }
142}
143
144/**
145 * @brief Fill template for Virtual Media Item.
146 */
Ed Tanous22db1722021-06-09 10:53:51 -0700147inline nlohmann::json vmItemTemplate(const std::string& name,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500148 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200149{
150 nlohmann::json item;
Ed Tanous22db1722021-06-09 10:53:51 -0700151
152 std::string id = "/redfish/v1/Managers/";
153 id += name;
154 id += "/VirtualMedia/";
155 id += resName;
156 item["@odata.id"] = std::move(id);
157
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100158 item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200159 item["Name"] = "Virtual Removable Media";
160 item["Id"] = resName;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200161 item["WriteProtected"] = true;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200162 item["MediaTypes"] = {"CD", "USBStick"};
163 item["TransferMethod"] = "Stream";
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100164 item["Oem"]["OpenBMC"]["@odata.type"] =
165 "#OemVirtualMedia.v1_0_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200166
167 return item;
168}
169
170/**
171 * @brief Fills collection data
172 */
Ed Tanous22db1722021-06-09 10:53:51 -0700173inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500174 const std::string& service,
175 const std::string& name)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200176{
177 BMCWEB_LOG_DEBUG << "Get available Virtual Media resources.";
178 crow::connections::systemBus->async_method_call(
Ed Tanous711ac7a2021-12-20 09:34:41 -0800179 [name,
180 aResp{std::move(aResp)}](const boost::system::error_code ec,
181 dbus::utility::ManagedObjectType& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700182 if (ec)
183 {
184 BMCWEB_LOG_DEBUG << "DBUS response error";
185 return;
186 }
187 nlohmann::json& members = aResp->res.jsonValue["Members"];
188 members = nlohmann::json::array();
189
190 for (const auto& object : subtree)
191 {
192 nlohmann::json item;
193 std::string path = object.first.filename();
194 if (path.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200195 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700196 continue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200197 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200198
Ed Tanous002d39b2022-05-31 08:59:27 -0700199 std::string id = "/redfish/v1/Managers/";
200 id += name;
201 id += "/VirtualMedia/";
202 id += path;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200203
Ed Tanous002d39b2022-05-31 08:59:27 -0700204 item["@odata.id"] = std::move(id);
205 members.emplace_back(std::move(item));
206 }
207 aResp->res.jsonValue["Members@odata.count"] = members.size();
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200208 },
209 service, "/xyz/openbmc_project/VirtualMedia",
210 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
211}
212
213/**
214 * @brief Fills data for specific resource
215 */
Ed Tanous22db1722021-06-09 10:53:51 -0700216inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500217 const std::string& service, const std::string& name,
218 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200219{
220 BMCWEB_LOG_DEBUG << "Get Virtual Media resource data.";
221
222 crow::connections::systemBus->async_method_call(
Ed Tanous914e2d52022-01-07 11:38:34 -0800223 [resName, name,
224 aResp](const boost::system::error_code ec,
225 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700226 if (ec)
227 {
228 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200229
Ed Tanous002d39b2022-05-31 08:59:27 -0700230 return;
231 }
232
233 for (const auto& item : subtree)
234 {
235 std::string thispath = item.first.filename();
236 if (thispath.empty())
237 {
238 continue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200239 }
240
Ed Tanous002d39b2022-05-31 08:59:27 -0700241 if (thispath != resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200242 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700243 continue;
244 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200245
Ed Tanous002d39b2022-05-31 08:59:27 -0700246 // "Legacy"/"Proxy"
247 auto mode = item.first.parent_path();
248 // "VirtualMedia"
249 auto type = mode.parent_path();
250 if (mode.filename().empty() || type.filename().empty())
251 {
252 continue;
253 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200254
Ed Tanous002d39b2022-05-31 08:59:27 -0700255 if (type.filename() != "VirtualMedia")
256 {
257 continue;
258 }
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200259
Ed Tanous002d39b2022-05-31 08:59:27 -0700260 aResp->res.jsonValue = vmItemTemplate(name, resName);
261 std::string actionsId = "/redfish/v1/Managers/";
262 actionsId += name;
263 actionsId += "/VirtualMedia/";
264 actionsId += resName;
265 actionsId += "/Actions";
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200266
Ed Tanous002d39b2022-05-31 08:59:27 -0700267 // Check if dbus path is Legacy type
268 if (mode.filename() == "Legacy")
269 {
270 aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200271 ["target"] =
Ed Tanous002d39b2022-05-31 08:59:27 -0700272 actionsId + "/VirtualMedia.InsertMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200273 }
274
Ed Tanous002d39b2022-05-31 08:59:27 -0700275 vmParseInterfaceObject(item.second, aResp);
276
277 aResp->res
278 .jsonValue["Actions"]["#VirtualMedia.EjectMedia"]["target"] =
279 actionsId + "/VirtualMedia.EjectMedia";
280
281 return;
282 }
283
284 messages::resourceNotFound(
285 aResp->res, "#VirtualMedia.v1_3_0.VirtualMedia", resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200286 },
287 service, "/xyz/openbmc_project/VirtualMedia",
288 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
289}
290
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200291/**
Ed Tanous22db1722021-06-09 10:53:51 -0700292 * @brief Transfer protocols supported for InsertMedia action.
293 *
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200294 */
Ed Tanous22db1722021-06-09 10:53:51 -0700295enum class TransferProtocol
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200296{
Ed Tanous22db1722021-06-09 10:53:51 -0700297 https,
298 smb,
299 invalid
300};
301
302/**
303 * @brief Function extracts transfer protocol type from URI.
304 *
305 */
Ed Tanous67df0732021-10-26 11:23:56 -0700306inline std::optional<TransferProtocol>
Ed Tanousace85d62021-10-26 12:45:59 -0700307 getTransferProtocolFromUri(const boost::urls::url_view& imageUri)
Ed Tanous67df0732021-10-26 11:23:56 -0700308{
Ed Tanousace85d62021-10-26 12:45:59 -0700309 boost::string_view scheme = imageUri.scheme();
Ed Tanous67df0732021-10-26 11:23:56 -0700310 if (scheme == "smb")
311 {
312 return TransferProtocol::smb;
313 }
314 if (scheme == "https")
315 {
316 return TransferProtocol::https;
317 }
318 if (!scheme.empty())
319 {
320 return TransferProtocol::invalid;
321 }
322
323 return {};
324}
Ed Tanous22db1722021-06-09 10:53:51 -0700325
326/**
327 * @brief Function convert transfer protocol from string param.
328 *
329 */
330inline std::optional<TransferProtocol> getTransferProtocolFromParam(
331 const std::optional<std::string>& transferProtocolType)
332{
333 if (transferProtocolType == std::nullopt)
Agata Olenderc6f4e012020-03-11 15:19:07 +0100334 {
Ed Tanous22db1722021-06-09 10:53:51 -0700335 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100336 }
337
Ed Tanous22db1722021-06-09 10:53:51 -0700338 if (*transferProtocolType == "CIFS")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200339 {
Ed Tanous22db1722021-06-09 10:53:51 -0700340 return TransferProtocol::smb;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200341 }
342
Ed Tanous22db1722021-06-09 10:53:51 -0700343 if (*transferProtocolType == "HTTPS")
344 {
345 return TransferProtocol::https;
346 }
347
348 return TransferProtocol::invalid;
349}
350
351/**
352 * @brief Function extends URI with transfer protocol type.
353 *
354 */
355inline std::string
356 getUriWithTransferProtocol(const std::string& imageUri,
357 const TransferProtocol& transferProtocol)
358{
359 if (transferProtocol == TransferProtocol::smb)
360 {
361 return "smb://" + imageUri;
362 }
363
364 if (transferProtocol == TransferProtocol::https)
365 {
366 return "https://" + imageUri;
367 }
368
369 return imageUri;
370}
371
372/**
373 * @brief Function validate parameters of insert media request.
374 *
375 */
376inline bool
377 validateParams(crow::Response& res, std::string& imageUrl,
378 const std::optional<bool>& inserted,
379 const std::optional<std::string>& transferMethod,
380 const std::optional<std::string>& transferProtocolType)
381{
382 BMCWEB_LOG_DEBUG << "Validation started";
383 // required param imageUrl must not be empty
384 if (imageUrl.empty())
385 {
386 BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
387
388 messages::propertyValueFormatError(res, "<empty>", "Image");
389
390 return false;
391 }
392
393 // optional param inserted must be true
Ed Tanouse05aec52022-01-25 10:28:56 -0800394 if ((inserted != std::nullopt) && !*inserted)
Ed Tanous22db1722021-06-09 10:53:51 -0700395 {
396 BMCWEB_LOG_ERROR
397 << "Request action optional parameter Inserted must be true.";
398
399 messages::actionParameterNotSupported(res, "Inserted", "InsertMedia");
400
401 return false;
402 }
403
404 // optional param transferMethod must be stream
405 if ((transferMethod != std::nullopt) && (*transferMethod != "Stream"))
406 {
407 BMCWEB_LOG_ERROR << "Request action optional parameter "
408 "TransferMethod must be Stream.";
409
410 messages::actionParameterNotSupported(res, "TransferMethod",
411 "InsertMedia");
412
413 return false;
414 }
Ed Tanousace85d62021-10-26 12:45:59 -0700415 boost::urls::result<boost::urls::url_view> url =
416 boost::urls::parse_uri(boost::string_view(imageUrl));
417 if (!url)
418 {
419 messages::resourceAtUriInUnknownFormat(res, *url);
420 return {};
421 }
Ed Tanous22db1722021-06-09 10:53:51 -0700422 std::optional<TransferProtocol> uriTransferProtocolType =
Ed Tanousace85d62021-10-26 12:45:59 -0700423 getTransferProtocolFromUri(*url);
Ed Tanous22db1722021-06-09 10:53:51 -0700424
425 std::optional<TransferProtocol> paramTransferProtocolType =
426 getTransferProtocolFromParam(transferProtocolType);
427
428 // ImageUrl does not contain valid protocol type
429 if (*uriTransferProtocolType == TransferProtocol::invalid)
430 {
431 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
432 "contain specified protocol type from list: "
433 "(smb, https).";
434
Ed Tanousace85d62021-10-26 12:45:59 -0700435 messages::resourceAtUriInUnknownFormat(res, *url);
Ed Tanous22db1722021-06-09 10:53:51 -0700436
437 return false;
438 }
439
440 // transferProtocolType should contain value from list
441 if (*paramTransferProtocolType == TransferProtocol::invalid)
442 {
443 BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
444 "must be provided with value from list: "
445 "(CIFS, HTTPS).";
446
447 messages::propertyValueNotInList(res, *transferProtocolType,
448 "TransferProtocolType");
449 return false;
450 }
451
452 // valid transfer protocol not provided either with URI nor param
453 if ((uriTransferProtocolType == std::nullopt) &&
454 (paramTransferProtocolType == std::nullopt))
455 {
456 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
457 "contain specified protocol type or param "
458 "TransferProtocolType must be provided.";
459
Ed Tanousace85d62021-10-26 12:45:59 -0700460 messages::resourceAtUriInUnknownFormat(res, *url);
Ed Tanous22db1722021-06-09 10:53:51 -0700461
462 return false;
463 }
464
465 // valid transfer protocol provided both with URI and param
466 if ((paramTransferProtocolType != std::nullopt) &&
467 (uriTransferProtocolType != std::nullopt))
468 {
469 // check if protocol is the same for URI and param
470 if (*paramTransferProtocolType != *uriTransferProtocolType)
471 {
472 BMCWEB_LOG_ERROR << "Request action parameter "
473 "TransferProtocolType must contain the "
474 "same protocol type as protocol type "
475 "provided with param imageUrl.";
476
477 messages::actionParameterValueTypeError(res, *transferProtocolType,
478 "TransferProtocolType",
479 "InsertMedia");
480
481 return false;
482 }
483 }
484
485 // validation passed
486 // add protocol to URI if needed
487 if (uriTransferProtocolType == std::nullopt)
488 {
489 imageUrl =
490 getUriWithTransferProtocol(imageUrl, *paramTransferProtocolType);
491 }
492
493 return true;
494}
495
496template <typename T>
497static void secureCleanup(T& value)
498{
Ed Tanous4ecc6182022-01-07 09:36:26 -0800499 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
Ed Tanous22db1722021-06-09 10:53:51 -0700500 auto raw = const_cast<typename T::value_type*>(value.data());
501 explicit_bzero(raw, value.size() * sizeof(*raw));
502}
503
504class Credentials
505{
506 public:
507 Credentials(std::string&& user, std::string&& password) :
508 userBuf(std::move(user)), passBuf(std::move(password))
509 {}
510
511 ~Credentials()
512 {
513 secureCleanup(userBuf);
514 secureCleanup(passBuf);
515 }
516
517 const std::string& user()
518 {
519 return userBuf;
520 }
521
522 const std::string& password()
523 {
524 return passBuf;
525 }
526
527 Credentials() = delete;
528 Credentials(const Credentials&) = delete;
529 Credentials& operator=(const Credentials&) = delete;
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800530 Credentials(Credentials&&) = delete;
531 Credentials& operator=(Credentials&&) = delete;
Ed Tanous22db1722021-06-09 10:53:51 -0700532
533 private:
534 std::string userBuf;
535 std::string passBuf;
536};
537
538class CredentialsProvider
539{
540 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500541 template <typename T>
Ed Tanous22db1722021-06-09 10:53:51 -0700542 struct Deleter
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100543 {
Ed Tanous22db1722021-06-09 10:53:51 -0700544 void operator()(T* buff) const
545 {
546 if (buff)
547 {
548 secureCleanup(*buff);
549 delete buff;
550 }
551 }
552 };
553
554 using Buffer = std::vector<char>;
555 using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
556 // Using explicit definition instead of std::function to avoid implicit
557 // conversions eg. stack copy instead of reference
558 using FormatterFunc = void(const std::string& username,
559 const std::string& password, Buffer& dest);
560
561 CredentialsProvider(std::string&& user, std::string&& password) :
562 credentials(std::move(user), std::move(password))
563 {}
564
565 const std::string& user()
566 {
567 return credentials.user();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100568 }
569
Ed Tanous22db1722021-06-09 10:53:51 -0700570 const std::string& password()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100571 {
Ed Tanous22db1722021-06-09 10:53:51 -0700572 return credentials.password();
573 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100574
Ed Tanous22db1722021-06-09 10:53:51 -0700575 SecureBuffer pack(FormatterFunc formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100576 {
Ed Tanous22db1722021-06-09 10:53:51 -0700577 SecureBuffer packed{new Buffer{}};
Ed Tanouse662eae2022-01-25 10:39:19 -0800578 if (formatter != nullptr)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100579 {
Ed Tanous22db1722021-06-09 10:53:51 -0700580 formatter(credentials.user(), credentials.password(), *packed);
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100581 }
582
Ed Tanous22db1722021-06-09 10:53:51 -0700583 return packed;
584 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100585
Ed Tanous22db1722021-06-09 10:53:51 -0700586 private:
587 Credentials credentials;
588};
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100589
Ed Tanous22db1722021-06-09 10:53:51 -0700590// Wrapper for boost::async_pipe ensuring proper pipe cleanup
591template <typename Buffer>
592class Pipe
593{
594 public:
595 using unix_fd = sdbusplus::message::unix_fd;
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100596
Ed Tanous22db1722021-06-09 10:53:51 -0700597 Pipe(boost::asio::io_context& io, Buffer&& buffer) :
598 impl(io), buffer{std::move(buffer)}
599 {}
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100600
Ed Tanous22db1722021-06-09 10:53:51 -0700601 ~Pipe()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100602 {
Ed Tanous22db1722021-06-09 10:53:51 -0700603 // Named pipe needs to be explicitly removed
604 impl.close();
605 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100606
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800607 Pipe(const Pipe&) = delete;
608 Pipe(Pipe&&) = delete;
609 Pipe& operator=(const Pipe&) = delete;
610 Pipe& operator=(Pipe&&) = delete;
611
Ed Tanous22db1722021-06-09 10:53:51 -0700612 unix_fd fd()
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200613 {
Ed Tanous22db1722021-06-09 10:53:51 -0700614 return unix_fd{impl.native_source()};
615 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100616
Ed Tanous22db1722021-06-09 10:53:51 -0700617 template <typename WriteHandler>
618 void asyncWrite(WriteHandler&& handler)
619 {
620 impl.async_write_some(data(), std::forward<WriteHandler>(handler));
621 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100622
Ed Tanous22db1722021-06-09 10:53:51 -0700623 private:
624 // Specialization for pointer types
625 template <typename B = Buffer>
626 typename std::enable_if<boost::has_dereference<B>::value,
627 boost::asio::const_buffer>::type
628 data()
629 {
630 return boost::asio::buffer(*buffer);
631 }
632
633 template <typename B = Buffer>
634 typename std::enable_if<!boost::has_dereference<B>::value,
635 boost::asio::const_buffer>::type
636 data()
637 {
638 return boost::asio::buffer(buffer);
639 }
640
641 const std::string name;
642 boost::process::async_pipe impl;
643 Buffer buffer;
644};
645
646/**
647 * @brief Function transceives data with dbus directly.
648 *
649 * All BMC state properties will be retrieved before sending reset request.
650 */
651inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
652 const std::string& service, const std::string& name,
653 const std::string& imageUrl, const bool rw,
654 std::string&& userName, std::string&& password)
655{
656 using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
657 constexpr const size_t secretLimit = 1024;
658
659 std::shared_ptr<SecurePipe> secretPipe;
Ed Tanous168e20c2021-12-13 14:39:53 -0800660 dbus::utility::DbusVariantType unixFd = -1;
Ed Tanous22db1722021-06-09 10:53:51 -0700661
662 if (!userName.empty() || !password.empty())
663 {
664 // Encapsulate in safe buffer
665 CredentialsProvider credentials(std::move(userName),
666 std::move(password));
667
668 // Payload must contain data + NULL delimiters
669 if (credentials.user().size() + credentials.password().size() + 2 >
670 secretLimit)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100671 {
Ed Tanous22db1722021-06-09 10:53:51 -0700672 BMCWEB_LOG_ERROR << "Credentials too long to handle";
673 messages::unrecognizedRequestBody(asyncResp->res);
674 return;
675 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100676
Ed Tanous22db1722021-06-09 10:53:51 -0700677 // Pack secret
678 auto secret = credentials.pack(
679 [](const auto& user, const auto& pass, auto& buff) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700680 std::copy(user.begin(), user.end(), std::back_inserter(buff));
681 buff.push_back('\0');
682 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
683 buff.push_back('\0');
684 });
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100685
Ed Tanous22db1722021-06-09 10:53:51 -0700686 // Open pipe
687 secretPipe = std::make_shared<SecurePipe>(
688 crow::connections::systemBus->get_io_context(), std::move(secret));
689 unixFd = secretPipe->fd();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100690
Ed Tanous22db1722021-06-09 10:53:51 -0700691 // Pass secret over pipe
692 secretPipe->asyncWrite(
693 [asyncResp](const boost::system::error_code& ec, std::size_t) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700694 if (ec)
695 {
696 BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
697 messages::internalError(asyncResp->res);
698 }
699 });
Ed Tanous22db1722021-06-09 10:53:51 -0700700 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100701
Ed Tanous22db1722021-06-09 10:53:51 -0700702 crow::connections::systemBus->async_method_call(
703 [asyncResp, secretPipe](const boost::system::error_code ec,
704 bool success) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700705 if (ec)
706 {
707 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
708 messages::internalError(asyncResp->res);
709 }
710 else if (!success)
711 {
712 BMCWEB_LOG_ERROR << "Service responded with error";
713 messages::generalError(asyncResp->res);
714 }
Ed Tanous22db1722021-06-09 10:53:51 -0700715 },
716 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
717 "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
718 unixFd);
719}
720
721/**
722 * @brief Function transceives data with dbus directly.
723 *
724 * All BMC state properties will be retrieved before sending reset request.
725 */
726inline void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
727 const std::string& service, const std::string& name,
728 bool legacy)
729{
730
731 // Legacy mount requires parameter with image
732 if (legacy)
733 {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100734 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700735 [asyncResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700736 if (ec)
737 {
738 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700739
Ed Tanous002d39b2022-05-31 08:59:27 -0700740 messages::internalError(asyncResp->res);
741 return;
742 }
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100743 },
744 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
Ed Tanous22db1722021-06-09 10:53:51 -0700745 "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200746 }
Ed Tanous22db1722021-06-09 10:53:51 -0700747 else // proxy
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200748 {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200749 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700750 [asyncResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700751 if (ec)
752 {
753 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700754
Ed Tanous002d39b2022-05-31 08:59:27 -0700755 messages::internalError(asyncResp->res);
756 return;
757 }
Ed Tanous22db1722021-06-09 10:53:51 -0700758 },
759 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
760 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
761 }
762}
763
Ed Tanous98be3e32021-09-16 15:05:36 -0700764struct InsertMediaActionParams
765{
766 std::string imageUrl;
767 std::optional<std::string> userName;
768 std::optional<std::string> password;
769 std::optional<std::string> transferMethod;
770 std::optional<std::string> transferProtocolType;
771 std::optional<bool> writeProtected = true;
772 std::optional<bool> inserted;
773};
774
Ed Tanous22db1722021-06-09 10:53:51 -0700775inline void requestNBDVirtualMediaRoutes(App& app)
776{
George Liu0fda0f12021-11-16 10:06:17 +0800777 BMCWEB_ROUTE(
778 app,
779 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
Ed Tanoused398212021-06-09 17:05:54 -0700780 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -0700781 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700782 [&app](const crow::Request& req,
783 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
784 const std::string& name, const std::string& resName) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700785 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
786 {
787 return;
788 }
789 if (name != "bmc")
790 {
791 messages::resourceNotFound(asyncResp->res, "VirtualMedia.Insert",
792 resName);
793
794 return;
795 }
796 InsertMediaActionParams actionParams;
797
798 // Read obligatory parameters (url of
799 // image)
800 if (!json_util::readJsonAction(
801 req, asyncResp->res, "Image", actionParams.imageUrl,
802 "WriteProtected", actionParams.writeProtected, "UserName",
803 actionParams.userName, "Password", actionParams.password,
804 "Inserted", actionParams.inserted, "TransferMethod",
805 actionParams.transferMethod, "TransferProtocolType",
806 actionParams.transferProtocolType))
807 {
808 BMCWEB_LOG_DEBUG << "Image is not provided";
809 return;
810 }
811
812 bool paramsValid = validateParams(
813 asyncResp->res, actionParams.imageUrl, actionParams.inserted,
814 actionParams.transferMethod, actionParams.transferProtocolType);
815
816 if (!paramsValid)
817 {
818 return;
819 }
820
821 crow::connections::systemBus->async_method_call(
822 [asyncResp, actionParams, resName](
823 const boost::system::error_code ec,
824 const dbus::utility::MapperGetObject& getObjectType) mutable {
825 if (ec)
826 {
827 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: "
828 << ec;
829 messages::internalError(asyncResp->res);
830
831 return;
832 }
833 std::string service = getObjectType.begin()->first;
834 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
835
836 crow::connections::systemBus->async_method_call(
837 [service, resName, actionParams,
838 asyncResp](const boost::system::error_code ec,
839 dbus::utility::ManagedObjectType& subtree) mutable {
840 if (ec)
Ed Tanous45ca1b82022-03-25 13:07:27 -0700841 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700842 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200843
844 return;
845 }
Ed Tanous98be3e32021-09-16 15:05:36 -0700846
Ed Tanous002d39b2022-05-31 08:59:27 -0700847 for (const auto& object : subtree)
Ed Tanous98be3e32021-09-16 15:05:36 -0700848 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700849 const std::string& path =
850 static_cast<const std::string&>(object.first);
Ed Tanous98be3e32021-09-16 15:05:36 -0700851
Ed Tanous002d39b2022-05-31 08:59:27 -0700852 std::size_t lastIndex = path.rfind('/');
853 if (lastIndex == std::string::npos)
854 {
855 continue;
856 }
Ed Tanous98be3e32021-09-16 15:05:36 -0700857
Ed Tanous002d39b2022-05-31 08:59:27 -0700858 lastIndex += 1;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200859
Ed Tanous002d39b2022-05-31 08:59:27 -0700860 if (path.substr(lastIndex) == resName)
861 {
862 lastIndex = path.rfind("Proxy");
863 if (lastIndex != std::string::npos)
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200864 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700865 // Not possible in proxy mode
866 BMCWEB_LOG_DEBUG << "InsertMedia not "
867 "allowed in proxy mode";
868 messages::resourceNotFound(
869 asyncResp->res, "VirtualMedia.InsertMedia",
870 resName);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200871
872 return;
873 }
874
Ed Tanous002d39b2022-05-31 08:59:27 -0700875 lastIndex = path.rfind("Legacy");
876 if (lastIndex == std::string::npos)
877 {
878 continue;
879 }
Ed Tanous22db1722021-06-09 10:53:51 -0700880
Ed Tanous002d39b2022-05-31 08:59:27 -0700881 // manager is irrelevant for
882 // VirtualMedia dbus calls
883 doMountVmLegacy(asyncResp, service, resName,
884 actionParams.imageUrl,
885 !(*actionParams.writeProtected),
886 std::move(*actionParams.userName),
887 std::move(*actionParams.password));
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200888
Ed Tanous002d39b2022-05-31 08:59:27 -0700889 return;
890 }
891 }
892 BMCWEB_LOG_DEBUG << "Parent item not found";
893 messages::resourceNotFound(asyncResp->res, "VirtualMedia",
894 resName);
895 },
896 service, "/xyz/openbmc_project/VirtualMedia",
897 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
898 },
899 "xyz.openbmc_project.ObjectMapper",
900 "/xyz/openbmc_project/object_mapper",
901 "xyz.openbmc_project.ObjectMapper", "GetObject",
902 "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>());
903 });
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200904
George Liu0fda0f12021-11-16 10:06:17 +0800905 BMCWEB_ROUTE(
906 app,
907 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
Ed Tanoused398212021-06-09 17:05:54 -0700908 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -0700909 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700910 [&app](const crow::Request& req,
911 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
912 const std::string& name, const std::string& resName) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700913 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
914 {
915 return;
916 }
917 if (name != "bmc")
918 {
919 messages::resourceNotFound(asyncResp->res, "VirtualMedia.Eject",
920 resName);
921
922 return;
923 }
924
925 crow::connections::systemBus->async_method_call(
926 [asyncResp,
927 resName](const boost::system::error_code ec,
928 const dbus::utility::MapperGetObject& getObjectType) {
929 if (ec)
930 {
931 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: "
932 << ec;
933 messages::internalError(asyncResp->res);
934
935 return;
936 }
937 std::string service = getObjectType.begin()->first;
938 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
939
940 crow::connections::systemBus->async_method_call(
941 [resName, service, asyncResp{asyncResp}](
942 const boost::system::error_code ec,
943 dbus::utility::ManagedObjectType& subtree) {
944 if (ec)
Ed Tanous45ca1b82022-03-25 13:07:27 -0700945 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700946 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200947
Ed Tanous22db1722021-06-09 10:53:51 -0700948 return;
949 }
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200950
Ed Tanous002d39b2022-05-31 08:59:27 -0700951 for (const auto& object : subtree)
952 {
953 const std::string& path =
954 static_cast<const std::string&>(object.first);
955
956 std::size_t lastIndex = path.rfind('/');
957 if (lastIndex == std::string::npos)
958 {
959 continue;
960 }
961
962 lastIndex += 1;
963
964 if (path.substr(lastIndex) == resName)
965 {
966 lastIndex = path.rfind("Proxy");
967 if (lastIndex != std::string::npos)
Ed Tanous22db1722021-06-09 10:53:51 -0700968 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700969 // Proxy mode
970 doVmAction(asyncResp, service, resName, false);
Ed Tanous22db1722021-06-09 10:53:51 -0700971 }
Ed Tanous22db1722021-06-09 10:53:51 -0700972
Ed Tanous002d39b2022-05-31 08:59:27 -0700973 lastIndex = path.rfind("Legacy");
974 if (lastIndex != std::string::npos)
975 {
976 // Legacy mode
977 doVmAction(asyncResp, service, resName, true);
978 }
Ed Tanous22db1722021-06-09 10:53:51 -0700979
Ed Tanous002d39b2022-05-31 08:59:27 -0700980 return;
981 }
982 }
983 BMCWEB_LOG_DEBUG << "Parent item not found";
984 messages::resourceNotFound(asyncResp->res, "VirtualMedia",
985 resName);
986 },
987 service, "/xyz/openbmc_project/VirtualMedia",
988 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
989 },
990 "xyz.openbmc_project.ObjectMapper",
991 "/xyz/openbmc_project/object_mapper",
992 "xyz.openbmc_project.ObjectMapper", "GetObject",
993 "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>());
994 });
Ed Tanous22db1722021-06-09 10:53:51 -0700995 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
Ed Tanoused398212021-06-09 17:05:54 -0700996 .privileges(redfish::privileges::getVirtualMediaCollection)
Ed Tanous22db1722021-06-09 10:53:51 -0700997 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700998 [&app](const crow::Request& req,
999 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1000 const std::string& name) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001001 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
1002 {
1003 return;
1004 }
1005 if (name != "bmc")
1006 {
1007 messages::resourceNotFound(asyncResp->res, "VirtualMedia", name);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001008
Ed Tanous002d39b2022-05-31 08:59:27 -07001009 return;
1010 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001011
Ed Tanous002d39b2022-05-31 08:59:27 -07001012 asyncResp->res.jsonValue["@odata.type"] =
1013 "#VirtualMediaCollection.VirtualMediaCollection";
1014 asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
1015 asyncResp->res.jsonValue["@odata.id"] =
1016 "/redfish/v1/Managers/" + name + "/VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001017
Ed Tanous002d39b2022-05-31 08:59:27 -07001018 crow::connections::systemBus->async_method_call(
1019 [asyncResp,
1020 name](const boost::system::error_code ec,
1021 const dbus::utility::MapperGetObject& getObjectType) {
1022 if (ec)
1023 {
1024 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: "
1025 << ec;
1026 messages::internalError(asyncResp->res);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001027
Ed Tanous002d39b2022-05-31 08:59:27 -07001028 return;
1029 }
1030 std::string service = getObjectType.begin()->first;
1031 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001032
Ed Tanous002d39b2022-05-31 08:59:27 -07001033 getVmResourceList(asyncResp, service, name);
1034 },
1035 "xyz.openbmc_project.ObjectMapper",
1036 "/xyz/openbmc_project/object_mapper",
1037 "xyz.openbmc_project.ObjectMapper", "GetObject",
1038 "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>());
1039 });
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001040
Ed Tanous22db1722021-06-09 10:53:51 -07001041 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001042 .privileges(redfish::privileges::getVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -07001043 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07001044 [&app](const crow::Request& req,
1045 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1046 const std::string& name, const std::string& resName) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001047 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
1048 {
1049 return;
1050 }
1051 if (name != "bmc")
1052 {
1053 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001054
Ed Tanous002d39b2022-05-31 08:59:27 -07001055 return;
1056 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001057
Ed Tanous002d39b2022-05-31 08:59:27 -07001058 crow::connections::systemBus->async_method_call(
1059 [asyncResp, name,
1060 resName](const boost::system::error_code ec,
1061 const dbus::utility::MapperGetObject& getObjectType) {
1062 if (ec)
1063 {
1064 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: "
1065 << ec;
1066 messages::internalError(asyncResp->res);
Ed Tanous22db1722021-06-09 10:53:51 -07001067
Ed Tanous002d39b2022-05-31 08:59:27 -07001068 return;
1069 }
1070 std::string service = getObjectType.begin()->first;
1071 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
Ed Tanous22db1722021-06-09 10:53:51 -07001072
Ed Tanous002d39b2022-05-31 08:59:27 -07001073 getVmData(asyncResp, service, name, resName);
1074 },
1075 "xyz.openbmc_project.ObjectMapper",
1076 "/xyz/openbmc_project/object_mapper",
1077 "xyz.openbmc_project.ObjectMapper", "GetObject",
1078 "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>());
1079 });
Ed Tanous22db1722021-06-09 10:53:51 -07001080}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001081
1082} // namespace redfish