blob: 9e44e80a7aacb656fe6b5de9b09e95a1d36ed52d [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
John Edward Broadbent7e860f12021-04-08 15:57:16 -070018#include <app.hpp>
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020019#include <boost/container/flat_map.hpp>
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +010020#include <boost/process/async_pipe.hpp>
21#include <boost/type_traits/has_dereference.hpp>
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020022#include <utils/json_utils.hpp>
23// for GetObjectType and ManagedObjectType
Ed Tanoused398212021-06-09 17:05:54 -070024
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +020025#include <account_service.hpp>
Anna Platash9e319cf2020-11-17 10:18:31 +010026#include <boost/url/url_view.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070027#include <registries/privilege_registry.hpp>
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020028
29namespace redfish
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020030{
Anna Platash9e319cf2020-11-17 10:18:31 +010031/**
32 * @brief Function extracts transfer protocol name from URI.
33 */
Ed Tanous67df0732021-10-26 11:23:56 -070034inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
35{
36 boost::urls::result<boost::urls::url_view> url =
37 boost::urls::parse_uri(boost::string_view(imageUri));
38 if (!url)
39 {
40 return "None";
41 }
42 boost::string_view scheme = url->scheme();
43 if (scheme == "smb")
44 {
45 return "CIFS";
46 }
47 if (scheme == "https")
48 {
49 return "HTTPS";
50 }
51
52 return "None";
53}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020054
55/**
56 * @brief Read all known properties from VM object interfaces
57 */
Ed Tanous22db1722021-06-09 10:53:51 -070058inline void
Ed Tanous711ac7a2021-12-20 09:34:41 -080059 vmParseInterfaceObject(const dbus::utility::DBusInteracesMap& interface,
zhanghch058d1b46d2021-04-01 11:18:24 +080060 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020061{
Ed Tanous711ac7a2021-12-20 09:34:41 -080062 for (const auto& [interface, values] : interface)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020063 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080064 if (interface == "xyz.openbmc_project.VirtualMedia.MountPoint")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020065 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080066 for (const auto& [property, value] : values)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020067 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080068 if (property == "EndpointId")
69 {
70 const std::string* endpointIdValue =
71 std::get_if<std::string>(&value);
72 if (endpointIdValue == nullptr)
73 {
74 continue;
75 }
76 if (!endpointIdValue->empty())
77 {
78 // Proxy mode
79 aResp->res
80 .jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
81 *endpointIdValue;
82 aResp->res.jsonValue["TransferProtocolType"] = "OEM";
83 }
84 }
85 if (property == "ImageURL")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020086 {
Anna Platash9e319cf2020-11-17 10:18:31 +010087 const std::string* imageUrlValue =
Ed Tanous711ac7a2021-12-20 09:34:41 -080088 std::get_if<std::string>(&value);
Ed Tanous26f69762022-01-25 09:49:11 -080089 if (imageUrlValue != nullptr && !imageUrlValue->empty())
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +010090 {
Anna Platash9e319cf2020-11-17 10:18:31 +010091 std::filesystem::path filePath = *imageUrlValue;
92 if (!filePath.has_filename())
93 {
94 // this will handle https share, which not
95 // necessarily has to have filename given.
96 aResp->res.jsonValue["ImageName"] = "";
97 }
98 else
99 {
100 aResp->res.jsonValue["ImageName"] =
101 filePath.filename();
102 }
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100103
Anna Platash9e319cf2020-11-17 10:18:31 +0100104 aResp->res.jsonValue["Image"] = *imageUrlValue;
Anna Platash9e319cf2020-11-17 10:18:31 +0100105 aResp->res.jsonValue["TransferProtocolType"] =
106 getTransferProtocolTypeFromUri(*imageUrlValue);
107
Ed Tanous711ac7a2021-12-20 09:34:41 -0800108 aResp->res.jsonValue["ConnectedVia"] = "URI";
Anna Platash9e319cf2020-11-17 10:18:31 +0100109 }
110 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800111 if (property == "WriteProtected")
Anna Platash9e319cf2020-11-17 10:18:31 +0100112 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800113 const bool* writeProtectedValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800114 if (writeProtectedValue != nullptr)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200115 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100116 aResp->res.jsonValue["WriteProtected"] =
117 *writeProtectedValue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200118 }
119 }
120 }
121 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800122 if (interface == "xyz.openbmc_project.VirtualMedia.Process")
123 {
124 for (const auto& [property, value] : values)
125 {
126 if (property == "Active")
127 {
128 const bool* activeValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800129 if (activeValue == nullptr)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800130 {
131 BMCWEB_LOG_DEBUG << "Value Active not found";
132 return;
133 }
134 aResp->res.jsonValue["Inserted"] = *activeValue;
135
Ed Tanouse05aec52022-01-25 10:28:56 -0800136 if (*activeValue)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800137 {
138 aResp->res.jsonValue["ConnectedVia"] = "Applet";
139 }
140 }
141 }
142 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200143 }
144}
145
146/**
147 * @brief Fill template for Virtual Media Item.
148 */
Ed Tanous22db1722021-06-09 10:53:51 -0700149inline nlohmann::json vmItemTemplate(const std::string& name,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500150 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200151{
152 nlohmann::json item;
Ed Tanous22db1722021-06-09 10:53:51 -0700153
154 std::string id = "/redfish/v1/Managers/";
155 id += name;
156 id += "/VirtualMedia/";
157 id += resName;
158 item["@odata.id"] = std::move(id);
159
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100160 item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200161 item["Name"] = "Virtual Removable Media";
162 item["Id"] = resName;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200163 item["WriteProtected"] = true;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200164 item["MediaTypes"] = {"CD", "USBStick"};
165 item["TransferMethod"] = "Stream";
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100166 item["Oem"]["OpenBMC"]["@odata.type"] =
167 "#OemVirtualMedia.v1_0_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200168
169 return item;
170}
171
172/**
173 * @brief Fills collection data
174 */
Ed Tanous22db1722021-06-09 10:53:51 -0700175inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500176 const std::string& service,
177 const std::string& name)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200178{
179 BMCWEB_LOG_DEBUG << "Get available Virtual Media resources.";
180 crow::connections::systemBus->async_method_call(
Ed Tanous711ac7a2021-12-20 09:34:41 -0800181 [name,
182 aResp{std::move(aResp)}](const boost::system::error_code ec,
183 dbus::utility::ManagedObjectType& subtree) {
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200184 if (ec)
185 {
186 BMCWEB_LOG_DEBUG << "DBUS response error";
187 return;
188 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500189 nlohmann::json& members = aResp->res.jsonValue["Members"];
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200190 members = nlohmann::json::array();
191
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500192 for (const auto& object : subtree)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200193 {
194 nlohmann::json item;
Ed Tanous2dfd18e2020-12-18 00:41:31 +0000195 std::string path = object.first.filename();
196 if (path.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200197 {
198 continue;
199 }
200
Ed Tanous22db1722021-06-09 10:53:51 -0700201 std::string id = "/redfish/v1/Managers/";
202 id += name;
203 id += "/VirtualMedia/";
204 id += path;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200205
Ed Tanous22db1722021-06-09 10:53:51 -0700206 item["@odata.id"] = std::move(id);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200207 members.emplace_back(std::move(item));
208 }
209 aResp->res.jsonValue["Members@odata.count"] = members.size();
210 },
211 service, "/xyz/openbmc_project/VirtualMedia",
212 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
213}
214
215/**
216 * @brief Fills data for specific resource
217 */
Ed Tanous22db1722021-06-09 10:53:51 -0700218inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500219 const std::string& service, const std::string& name,
220 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200221{
222 BMCWEB_LOG_DEBUG << "Get Virtual Media resource data.";
223
224 crow::connections::systemBus->async_method_call(
Ed Tanous914e2d52022-01-07 11:38:34 -0800225 [resName, name,
226 aResp](const boost::system::error_code ec,
227 const dbus::utility::ManagedObjectType& subtree) {
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200228 if (ec)
229 {
230 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200231
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200232 return;
233 }
234
Ed Tanous914e2d52022-01-07 11:38:34 -0800235 for (const auto& item : subtree)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200236 {
Ed Tanous2dfd18e2020-12-18 00:41:31 +0000237 std::string thispath = item.first.filename();
238 if (thispath.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200239 {
240 continue;
241 }
242
Ed Tanous2dfd18e2020-12-18 00:41:31 +0000243 if (thispath != resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200244 {
245 continue;
246 }
247
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200248 // "Legacy"/"Proxy"
249 auto mode = item.first.parent_path();
250 // "VirtualMedia"
251 auto type = mode.parent_path();
252 if (mode.filename().empty() || type.filename().empty())
253 {
254 continue;
255 }
256
257 if (type.filename() != "VirtualMedia")
258 {
259 continue;
260 }
261
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200262 aResp->res.jsonValue = vmItemTemplate(name, resName);
Ed Tanous22db1722021-06-09 10:53:51 -0700263 std::string actionsId = "/redfish/v1/Managers/";
264 actionsId += name;
265 actionsId += "/VirtualMedia/";
266 actionsId += resName;
267 actionsId += "/Actions";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200268
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200269 // Check if dbus path is Legacy type
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200270 if (mode.filename() == "Legacy")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200271 {
272 aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
273 ["target"] =
Ed Tanous22db1722021-06-09 10:53:51 -0700274 actionsId + "/VirtualMedia.InsertMedia";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200275 }
276
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200277 vmParseInterfaceObject(item.second, aResp);
278
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200279 aResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"]
280 ["target"] =
Ed Tanous22db1722021-06-09 10:53:51 -0700281 actionsId + "/VirtualMedia.EjectMedia";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200282
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200283 return;
284 }
285
286 messages::resourceNotFound(
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100287 aResp->res, "#VirtualMedia.v1_3_0.VirtualMedia", resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200288 },
289 service, "/xyz/openbmc_project/VirtualMedia",
290 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
291}
292
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200293/**
Ed Tanous22db1722021-06-09 10:53:51 -0700294 * @brief Transfer protocols supported for InsertMedia action.
295 *
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200296 */
Ed Tanous22db1722021-06-09 10:53:51 -0700297enum class TransferProtocol
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200298{
Ed Tanous22db1722021-06-09 10:53:51 -0700299 https,
300 smb,
301 invalid
302};
303
304/**
305 * @brief Function extracts transfer protocol type from URI.
306 *
307 */
Ed Tanous67df0732021-10-26 11:23:56 -0700308inline std::optional<TransferProtocol>
309 getTransferProtocolFromUri(const std::string& imageUri)
310{
311 boost::urls::result<boost::urls::url_view> url =
312 boost::urls::parse_uri(boost::string_view(imageUri));
313 if (!url)
314 {
315 return {};
316 }
317
318 boost::string_view scheme = url->scheme();
319 if (scheme == "smb")
320 {
321 return TransferProtocol::smb;
322 }
323 if (scheme == "https")
324 {
325 return TransferProtocol::https;
326 }
327 if (!scheme.empty())
328 {
329 return TransferProtocol::invalid;
330 }
331
332 return {};
333}
Ed Tanous22db1722021-06-09 10:53:51 -0700334
335/**
336 * @brief Function convert transfer protocol from string param.
337 *
338 */
339inline std::optional<TransferProtocol> getTransferProtocolFromParam(
340 const std::optional<std::string>& transferProtocolType)
341{
342 if (transferProtocolType == std::nullopt)
Agata Olenderc6f4e012020-03-11 15:19:07 +0100343 {
Ed Tanous22db1722021-06-09 10:53:51 -0700344 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100345 }
346
Ed Tanous22db1722021-06-09 10:53:51 -0700347 if (*transferProtocolType == "CIFS")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200348 {
Ed Tanous22db1722021-06-09 10:53:51 -0700349 return TransferProtocol::smb;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200350 }
351
Ed Tanous22db1722021-06-09 10:53:51 -0700352 if (*transferProtocolType == "HTTPS")
353 {
354 return TransferProtocol::https;
355 }
356
357 return TransferProtocol::invalid;
358}
359
360/**
361 * @brief Function extends URI with transfer protocol type.
362 *
363 */
364inline std::string
365 getUriWithTransferProtocol(const std::string& imageUri,
366 const TransferProtocol& transferProtocol)
367{
368 if (transferProtocol == TransferProtocol::smb)
369 {
370 return "smb://" + imageUri;
371 }
372
373 if (transferProtocol == TransferProtocol::https)
374 {
375 return "https://" + imageUri;
376 }
377
378 return imageUri;
379}
380
381/**
382 * @brief Function validate parameters of insert media request.
383 *
384 */
385inline bool
386 validateParams(crow::Response& res, std::string& imageUrl,
387 const std::optional<bool>& inserted,
388 const std::optional<std::string>& transferMethod,
389 const std::optional<std::string>& transferProtocolType)
390{
391 BMCWEB_LOG_DEBUG << "Validation started";
392 // required param imageUrl must not be empty
393 if (imageUrl.empty())
394 {
395 BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
396
397 messages::propertyValueFormatError(res, "<empty>", "Image");
398
399 return false;
400 }
401
402 // optional param inserted must be true
Ed Tanouse05aec52022-01-25 10:28:56 -0800403 if ((inserted != std::nullopt) && !*inserted)
Ed Tanous22db1722021-06-09 10:53:51 -0700404 {
405 BMCWEB_LOG_ERROR
406 << "Request action optional parameter Inserted must be true.";
407
408 messages::actionParameterNotSupported(res, "Inserted", "InsertMedia");
409
410 return false;
411 }
412
413 // optional param transferMethod must be stream
414 if ((transferMethod != std::nullopt) && (*transferMethod != "Stream"))
415 {
416 BMCWEB_LOG_ERROR << "Request action optional parameter "
417 "TransferMethod must be Stream.";
418
419 messages::actionParameterNotSupported(res, "TransferMethod",
420 "InsertMedia");
421
422 return false;
423 }
424
425 std::optional<TransferProtocol> uriTransferProtocolType =
426 getTransferProtocolFromUri(imageUrl);
427
428 std::optional<TransferProtocol> paramTransferProtocolType =
429 getTransferProtocolFromParam(transferProtocolType);
430
431 // ImageUrl does not contain valid protocol type
432 if (*uriTransferProtocolType == TransferProtocol::invalid)
433 {
434 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
435 "contain specified protocol type from list: "
436 "(smb, https).";
437
438 messages::resourceAtUriInUnknownFormat(res, imageUrl);
439
440 return false;
441 }
442
443 // transferProtocolType should contain value from list
444 if (*paramTransferProtocolType == TransferProtocol::invalid)
445 {
446 BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
447 "must be provided with value from list: "
448 "(CIFS, HTTPS).";
449
450 messages::propertyValueNotInList(res, *transferProtocolType,
451 "TransferProtocolType");
452 return false;
453 }
454
455 // valid transfer protocol not provided either with URI nor param
456 if ((uriTransferProtocolType == std::nullopt) &&
457 (paramTransferProtocolType == std::nullopt))
458 {
459 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
460 "contain specified protocol type or param "
461 "TransferProtocolType must be provided.";
462
463 messages::resourceAtUriInUnknownFormat(res, imageUrl);
464
465 return false;
466 }
467
468 // valid transfer protocol provided both with URI and param
469 if ((paramTransferProtocolType != std::nullopt) &&
470 (uriTransferProtocolType != std::nullopt))
471 {
472 // check if protocol is the same for URI and param
473 if (*paramTransferProtocolType != *uriTransferProtocolType)
474 {
475 BMCWEB_LOG_ERROR << "Request action parameter "
476 "TransferProtocolType must contain the "
477 "same protocol type as protocol type "
478 "provided with param imageUrl.";
479
480 messages::actionParameterValueTypeError(res, *transferProtocolType,
481 "TransferProtocolType",
482 "InsertMedia");
483
484 return false;
485 }
486 }
487
488 // validation passed
489 // add protocol to URI if needed
490 if (uriTransferProtocolType == std::nullopt)
491 {
492 imageUrl =
493 getUriWithTransferProtocol(imageUrl, *paramTransferProtocolType);
494 }
495
496 return true;
497}
498
499template <typename T>
500static void secureCleanup(T& value)
501{
Ed Tanous4ecc6182022-01-07 09:36:26 -0800502 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
Ed Tanous22db1722021-06-09 10:53:51 -0700503 auto raw = const_cast<typename T::value_type*>(value.data());
504 explicit_bzero(raw, value.size() * sizeof(*raw));
505}
506
507class Credentials
508{
509 public:
510 Credentials(std::string&& user, std::string&& password) :
511 userBuf(std::move(user)), passBuf(std::move(password))
512 {}
513
514 ~Credentials()
515 {
516 secureCleanup(userBuf);
517 secureCleanup(passBuf);
518 }
519
520 const std::string& user()
521 {
522 return userBuf;
523 }
524
525 const std::string& password()
526 {
527 return passBuf;
528 }
529
530 Credentials() = delete;
531 Credentials(const Credentials&) = delete;
532 Credentials& operator=(const Credentials&) = delete;
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800533 Credentials(Credentials&&) = delete;
534 Credentials& operator=(Credentials&&) = delete;
Ed Tanous22db1722021-06-09 10:53:51 -0700535
536 private:
537 std::string userBuf;
538 std::string passBuf;
539};
540
541class CredentialsProvider
542{
543 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500544 template <typename T>
Ed Tanous22db1722021-06-09 10:53:51 -0700545 struct Deleter
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100546 {
Ed Tanous22db1722021-06-09 10:53:51 -0700547 void operator()(T* buff) const
548 {
549 if (buff)
550 {
551 secureCleanup(*buff);
552 delete buff;
553 }
554 }
555 };
556
557 using Buffer = std::vector<char>;
558 using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
559 // Using explicit definition instead of std::function to avoid implicit
560 // conversions eg. stack copy instead of reference
561 using FormatterFunc = void(const std::string& username,
562 const std::string& password, Buffer& dest);
563
564 CredentialsProvider(std::string&& user, std::string&& password) :
565 credentials(std::move(user), std::move(password))
566 {}
567
568 const std::string& user()
569 {
570 return credentials.user();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100571 }
572
Ed Tanous22db1722021-06-09 10:53:51 -0700573 const std::string& password()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100574 {
Ed Tanous22db1722021-06-09 10:53:51 -0700575 return credentials.password();
576 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100577
Ed Tanous22db1722021-06-09 10:53:51 -0700578 SecureBuffer pack(FormatterFunc formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100579 {
Ed Tanous22db1722021-06-09 10:53:51 -0700580 SecureBuffer packed{new Buffer{}};
Ed Tanouse662eae2022-01-25 10:39:19 -0800581 if (formatter != nullptr)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100582 {
Ed Tanous22db1722021-06-09 10:53:51 -0700583 formatter(credentials.user(), credentials.password(), *packed);
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100584 }
585
Ed Tanous22db1722021-06-09 10:53:51 -0700586 return packed;
587 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100588
Ed Tanous22db1722021-06-09 10:53:51 -0700589 private:
590 Credentials credentials;
591};
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100592
Ed Tanous22db1722021-06-09 10:53:51 -0700593// Wrapper for boost::async_pipe ensuring proper pipe cleanup
594template <typename Buffer>
595class Pipe
596{
597 public:
598 using unix_fd = sdbusplus::message::unix_fd;
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100599
Ed Tanous22db1722021-06-09 10:53:51 -0700600 Pipe(boost::asio::io_context& io, Buffer&& buffer) :
601 impl(io), buffer{std::move(buffer)}
602 {}
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100603
Ed Tanous22db1722021-06-09 10:53:51 -0700604 ~Pipe()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100605 {
Ed Tanous22db1722021-06-09 10:53:51 -0700606 // Named pipe needs to be explicitly removed
607 impl.close();
608 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100609
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800610 Pipe(const Pipe&) = delete;
611 Pipe(Pipe&&) = delete;
612 Pipe& operator=(const Pipe&) = delete;
613 Pipe& operator=(Pipe&&) = delete;
614
Ed Tanous22db1722021-06-09 10:53:51 -0700615 unix_fd fd()
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200616 {
Ed Tanous22db1722021-06-09 10:53:51 -0700617 return unix_fd{impl.native_source()};
618 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100619
Ed Tanous22db1722021-06-09 10:53:51 -0700620 template <typename WriteHandler>
621 void asyncWrite(WriteHandler&& handler)
622 {
623 impl.async_write_some(data(), std::forward<WriteHandler>(handler));
624 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100625
Ed Tanous22db1722021-06-09 10:53:51 -0700626 private:
627 // Specialization for pointer types
628 template <typename B = Buffer>
629 typename std::enable_if<boost::has_dereference<B>::value,
630 boost::asio::const_buffer>::type
631 data()
632 {
633 return boost::asio::buffer(*buffer);
634 }
635
636 template <typename B = Buffer>
637 typename std::enable_if<!boost::has_dereference<B>::value,
638 boost::asio::const_buffer>::type
639 data()
640 {
641 return boost::asio::buffer(buffer);
642 }
643
644 const std::string name;
645 boost::process::async_pipe impl;
646 Buffer buffer;
647};
648
649/**
650 * @brief Function transceives data with dbus directly.
651 *
652 * All BMC state properties will be retrieved before sending reset request.
653 */
654inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
655 const std::string& service, const std::string& name,
656 const std::string& imageUrl, const bool rw,
657 std::string&& userName, std::string&& password)
658{
659 using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
660 constexpr const size_t secretLimit = 1024;
661
662 std::shared_ptr<SecurePipe> secretPipe;
Ed Tanous168e20c2021-12-13 14:39:53 -0800663 dbus::utility::DbusVariantType unixFd = -1;
Ed Tanous22db1722021-06-09 10:53:51 -0700664
665 if (!userName.empty() || !password.empty())
666 {
667 // Encapsulate in safe buffer
668 CredentialsProvider credentials(std::move(userName),
669 std::move(password));
670
671 // Payload must contain data + NULL delimiters
672 if (credentials.user().size() + credentials.password().size() + 2 >
673 secretLimit)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100674 {
Ed Tanous22db1722021-06-09 10:53:51 -0700675 BMCWEB_LOG_ERROR << "Credentials too long to handle";
676 messages::unrecognizedRequestBody(asyncResp->res);
677 return;
678 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100679
Ed Tanous22db1722021-06-09 10:53:51 -0700680 // Pack secret
681 auto secret = credentials.pack(
682 [](const auto& user, const auto& pass, auto& buff) {
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100683 std::copy(user.begin(), user.end(), std::back_inserter(buff));
684 buff.push_back('\0');
685 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
686 buff.push_back('\0');
687 });
688
Ed Tanous22db1722021-06-09 10:53:51 -0700689 // Open pipe
690 secretPipe = std::make_shared<SecurePipe>(
691 crow::connections::systemBus->get_io_context(), std::move(secret));
692 unixFd = secretPipe->fd();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100693
Ed Tanous22db1722021-06-09 10:53:51 -0700694 // Pass secret over pipe
695 secretPipe->asyncWrite(
696 [asyncResp](const boost::system::error_code& ec, std::size_t) {
697 if (ec)
698 {
699 BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
700 messages::internalError(asyncResp->res);
701 }
702 });
703 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100704
Ed Tanous22db1722021-06-09 10:53:51 -0700705 crow::connections::systemBus->async_method_call(
706 [asyncResp, secretPipe](const boost::system::error_code ec,
707 bool success) {
708 if (ec)
709 {
710 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
711 messages::internalError(asyncResp->res);
712 }
713 else if (!success)
714 {
715 BMCWEB_LOG_ERROR << "Service responded with error";
716 messages::generalError(asyncResp->res);
717 }
718 },
719 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
720 "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
721 unixFd);
722}
723
724/**
725 * @brief Function transceives data with dbus directly.
726 *
727 * All BMC state properties will be retrieved before sending reset request.
728 */
729inline void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
730 const std::string& service, const std::string& name,
731 bool legacy)
732{
733
734 // Legacy mount requires parameter with image
735 if (legacy)
736 {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100737 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700738 [asyncResp](const boost::system::error_code ec) {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100739 if (ec)
740 {
741 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700742
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100743 messages::internalError(asyncResp->res);
Ed Tanous22db1722021-06-09 10:53:51 -0700744 return;
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100745 }
746 },
747 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
Ed Tanous22db1722021-06-09 10:53:51 -0700748 "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200749 }
Ed Tanous22db1722021-06-09 10:53:51 -0700750 else // proxy
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200751 {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200752 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700753 [asyncResp](const boost::system::error_code ec) {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200754 if (ec)
755 {
Ed Tanous22db1722021-06-09 10:53:51 -0700756 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
757
zhanghch058d1b46d2021-04-01 11:18:24 +0800758 messages::internalError(asyncResp->res);
Ed Tanous22db1722021-06-09 10:53:51 -0700759 return;
760 }
761 },
762 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
763 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
764 }
765}
766
Ed Tanous98be3e32021-09-16 15:05:36 -0700767struct InsertMediaActionParams
768{
769 std::string imageUrl;
770 std::optional<std::string> userName;
771 std::optional<std::string> password;
772 std::optional<std::string> transferMethod;
773 std::optional<std::string> transferProtocolType;
774 std::optional<bool> writeProtected = true;
775 std::optional<bool> inserted;
776};
777
Ed Tanous22db1722021-06-09 10:53:51 -0700778inline void requestNBDVirtualMediaRoutes(App& app)
779{
George Liu0fda0f12021-11-16 10:06:17 +0800780 BMCWEB_ROUTE(
781 app,
782 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
Ed Tanoused398212021-06-09 17:05:54 -0700783 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -0700784 .methods(boost::beast::http::verb::post)(
785 [](const crow::Request& req,
786 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
787 const std::string& name, const std::string& resName) {
788 if (name != "bmc")
789 {
790 messages::resourceNotFound(asyncResp->res,
791 "VirtualMedia.Insert", resName);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200792
793 return;
794 }
Ed Tanous98be3e32021-09-16 15:05:36 -0700795 InsertMediaActionParams actionParams;
796
797 // Read obligatory parameters (url of
798 // image)
799 if (!json_util::readJson(
800 req, asyncResp->res, "Image", actionParams.imageUrl,
801 "WriteProtected", actionParams.writeProtected,
802 "UserName", actionParams.userName, "Password",
803 actionParams.password, "Inserted",
804 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,
814 actionParams.inserted, actionParams.transferMethod,
815 actionParams.transferProtocolType);
816
Ed Tanouse05aec52022-01-25 10:28:56 -0800817 if (!paramsValid)
Ed Tanous98be3e32021-09-16 15:05:36 -0700818 {
819 return;
820 }
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200821
822 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700823 [asyncResp, actionParams,
Ed Tanous22db1722021-06-09 10:53:51 -0700824 resName](const boost::system::error_code ec,
Ed Tanous98be3e32021-09-16 15:05:36 -0700825 const GetObjectType& getObjectType) mutable {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200826 if (ec)
827 {
Ed Tanous22db1722021-06-09 10:53:51 -0700828 BMCWEB_LOG_ERROR
829 << "ObjectMapper::GetObject call failed: "
830 << ec;
831 messages::internalError(asyncResp->res);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200832
833 return;
834 }
Ed Tanous22db1722021-06-09 10:53:51 -0700835 std::string service = getObjectType.begin()->first;
836 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200837
Ed Tanous22db1722021-06-09 10:53:51 -0700838 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700839 [service, resName, actionParams,
Ed Tanous22db1722021-06-09 10:53:51 -0700840 asyncResp](const boost::system::error_code ec,
Ed Tanous711ac7a2021-12-20 09:34:41 -0800841 dbus::utility::ManagedObjectType&
842 subtree) mutable {
Ed Tanous22db1722021-06-09 10:53:51 -0700843 if (ec)
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200844 {
Ed Tanous22db1722021-06-09 10:53:51 -0700845 BMCWEB_LOG_DEBUG << "DBUS response error";
846
847 return;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200848 }
849
Ed Tanous22db1722021-06-09 10:53:51 -0700850 for (const auto& object : subtree)
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200851 {
Ed Tanous22db1722021-06-09 10:53:51 -0700852 const std::string& path =
853 static_cast<const std::string&>(
854 object.first);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200855
Ed Tanous22db1722021-06-09 10:53:51 -0700856 std::size_t lastIndex = path.rfind('/');
857 if (lastIndex == std::string::npos)
858 {
859 continue;
860 }
861
862 lastIndex += 1;
863
864 if (path.substr(lastIndex) == resName)
865 {
866 lastIndex = path.rfind("Proxy");
867 if (lastIndex != std::string::npos)
868 {
869 // Not possible in proxy mode
870 BMCWEB_LOG_DEBUG
871 << "InsertMedia not "
872 "allowed in proxy mode";
873 messages::resourceNotFound(
874 asyncResp->res,
875 "VirtualMedia.InsertMedia",
876 resName);
877
878 return;
879 }
880
881 lastIndex = path.rfind("Legacy");
882 if (lastIndex == std::string::npos)
883 {
884 continue;
885 }
886
Ed Tanous22db1722021-06-09 10:53:51 -0700887 // manager is irrelevant for
888 // VirtualMedia dbus calls
Ed Tanous98be3e32021-09-16 15:05:36 -0700889 doMountVmLegacy(
890 asyncResp, service, resName,
891 actionParams.imageUrl,
892 !(*actionParams.writeProtected),
893 std::move(*actionParams.userName),
894 std::move(*actionParams.password));
Ed Tanous22db1722021-06-09 10:53:51 -0700895
896 return;
897 }
898 }
899 BMCWEB_LOG_DEBUG << "Parent item not found";
900 messages::resourceNotFound(
901 asyncResp->res, "VirtualMedia", resName);
902 },
903 service, "/xyz/openbmc_project/VirtualMedia",
904 "org.freedesktop.DBus.ObjectManager",
905 "GetManagedObjects");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200906 },
Ed Tanous22db1722021-06-09 10:53:51 -0700907 "xyz.openbmc_project.ObjectMapper",
908 "/xyz/openbmc_project/object_mapper",
909 "xyz.openbmc_project.ObjectMapper", "GetObject",
910 "/xyz/openbmc_project/VirtualMedia",
911 std::array<const char*, 0>());
912 });
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200913
George Liu0fda0f12021-11-16 10:06:17 +0800914 BMCWEB_ROUTE(
915 app,
916 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
Ed Tanoused398212021-06-09 17:05:54 -0700917 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -0700918 .methods(boost::beast::http::verb::post)(
Ed Tanous98be3e32021-09-16 15:05:36 -0700919 [](const crow::Request&,
Ed Tanous22db1722021-06-09 10:53:51 -0700920 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
921 const std::string& name, const std::string& resName) {
922 if (name != "bmc")
923 {
924 messages::resourceNotFound(asyncResp->res,
925 "VirtualMedia.Eject", resName);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200926
Ed Tanous22db1722021-06-09 10:53:51 -0700927 return;
928 }
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200929
Ed Tanous22db1722021-06-09 10:53:51 -0700930 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700931 [asyncResp, resName](const boost::system::error_code ec,
932 const GetObjectType& getObjectType) {
Ed Tanous22db1722021-06-09 10:53:51 -0700933 if (ec)
934 {
935 BMCWEB_LOG_ERROR
936 << "ObjectMapper::GetObject call failed: "
937 << ec;
938 messages::internalError(asyncResp->res);
939
940 return;
941 }
942 std::string service = getObjectType.begin()->first;
943 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
944
945 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700946 [resName, service, asyncResp{asyncResp}](
Ed Tanous22db1722021-06-09 10:53:51 -0700947 const boost::system::error_code ec,
Ed Tanous711ac7a2021-12-20 09:34:41 -0800948 dbus::utility::ManagedObjectType& subtree) {
Ed Tanous22db1722021-06-09 10:53:51 -0700949 if (ec)
950 {
951 BMCWEB_LOG_DEBUG << "DBUS response error";
952
953 return;
954 }
955
956 for (const auto& object : subtree)
957 {
958 const std::string& path =
959 static_cast<const std::string&>(
960 object.first);
961
962 std::size_t lastIndex = path.rfind('/');
963 if (lastIndex == std::string::npos)
964 {
965 continue;
966 }
967
968 lastIndex += 1;
969
970 if (path.substr(lastIndex) == resName)
971 {
972 lastIndex = path.rfind("Proxy");
973 if (lastIndex != std::string::npos)
974 {
975 // Proxy mode
976 doVmAction(asyncResp, service,
977 resName, false);
978 }
979
980 lastIndex = path.rfind("Legacy");
981 if (lastIndex != std::string::npos)
982 {
983 // Legacy mode
984 doVmAction(asyncResp, service,
985 resName, true);
986 }
987
988 return;
989 }
990 }
991 BMCWEB_LOG_DEBUG << "Parent item not found";
992 messages::resourceNotFound(
993 asyncResp->res, "VirtualMedia", resName);
994 },
995 service, "/xyz/openbmc_project/VirtualMedia",
996 "org.freedesktop.DBus.ObjectManager",
997 "GetManagedObjects");
998 },
999 "xyz.openbmc_project.ObjectMapper",
1000 "/xyz/openbmc_project/object_mapper",
1001 "xyz.openbmc_project.ObjectMapper", "GetObject",
1002 "/xyz/openbmc_project/VirtualMedia",
1003 std::array<const char*, 0>());
1004 });
1005 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
Ed Tanoused398212021-06-09 17:05:54 -07001006 .privileges(redfish::privileges::getVirtualMediaCollection)
Ed Tanous22db1722021-06-09 10:53:51 -07001007 .methods(boost::beast::http::verb::get)(
1008 [](const crow::Request& /* req */,
1009 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1010 const std::string& name) {
1011 if (name != "bmc")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001012 {
Ed Tanous22db1722021-06-09 10:53:51 -07001013 messages::resourceNotFound(asyncResp->res, "VirtualMedia",
1014 name);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001015
1016 return;
1017 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001018
Ed Tanous22db1722021-06-09 10:53:51 -07001019 asyncResp->res.jsonValue["@odata.type"] =
1020 "#VirtualMediaCollection.VirtualMediaCollection";
1021 asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
1022 asyncResp->res.jsonValue["@odata.id"] =
1023 "/redfish/v1/Managers/" + name + "/VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001024
Ed Tanous22db1722021-06-09 10:53:51 -07001025 crow::connections::systemBus->async_method_call(
1026 [asyncResp, name](const boost::system::error_code ec,
1027 const GetObjectType& getObjectType) {
1028 if (ec)
1029 {
1030 BMCWEB_LOG_ERROR
1031 << "ObjectMapper::GetObject call failed: "
1032 << ec;
1033 messages::internalError(asyncResp->res);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001034
Ed Tanous22db1722021-06-09 10:53:51 -07001035 return;
1036 }
1037 std::string service = getObjectType.begin()->first;
1038 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001039
Ed Tanous22db1722021-06-09 10:53:51 -07001040 getVmResourceList(asyncResp, service, name);
1041 },
1042 "xyz.openbmc_project.ObjectMapper",
1043 "/xyz/openbmc_project/object_mapper",
1044 "xyz.openbmc_project.ObjectMapper", "GetObject",
1045 "/xyz/openbmc_project/VirtualMedia",
1046 std::array<const char*, 0>());
1047 });
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001048
Ed Tanous22db1722021-06-09 10:53:51 -07001049 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001050 .privileges(redfish::privileges::getVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -07001051 .methods(boost::beast::http::verb::get)(
1052 [](const crow::Request& /* req */,
1053 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1054 const std::string& name, const std::string& resName) {
1055 if (name != "bmc")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001056 {
Ed Tanous22db1722021-06-09 10:53:51 -07001057 messages::resourceNotFound(asyncResp->res, "VirtualMedia",
1058 resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001059
1060 return;
1061 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001062
Ed Tanous22db1722021-06-09 10:53:51 -07001063 crow::connections::systemBus->async_method_call(
1064 [asyncResp, name,
1065 resName](const boost::system::error_code ec,
1066 const GetObjectType& getObjectType) {
1067 if (ec)
1068 {
1069 BMCWEB_LOG_ERROR
1070 << "ObjectMapper::GetObject call failed: "
1071 << ec;
1072 messages::internalError(asyncResp->res);
1073
1074 return;
1075 }
1076 std::string service = getObjectType.begin()->first;
1077 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1078
1079 getVmData(asyncResp, service, name, resName);
1080 },
1081 "xyz.openbmc_project.ObjectMapper",
1082 "/xyz/openbmc_project/object_mapper",
1083 "xyz.openbmc_project.ObjectMapper", "GetObject",
1084 "/xyz/openbmc_project/VirtualMedia",
1085 std::array<const char*, 0>());
1086 });
1087}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001088
1089} // namespace redfish