blob: b0e3b38c34cb1513cbca3fb34ff6a00a9bf091d2 [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>
Ed Tanousace85d62021-10-26 12:45:59 -0700309 getTransferProtocolFromUri(const boost::urls::url_view& imageUri)
Ed Tanous67df0732021-10-26 11:23:56 -0700310{
Ed Tanousace85d62021-10-26 12:45:59 -0700311 boost::string_view scheme = imageUri.scheme();
Ed Tanous67df0732021-10-26 11:23:56 -0700312 if (scheme == "smb")
313 {
314 return TransferProtocol::smb;
315 }
316 if (scheme == "https")
317 {
318 return TransferProtocol::https;
319 }
320 if (!scheme.empty())
321 {
322 return TransferProtocol::invalid;
323 }
324
325 return {};
326}
Ed Tanous22db1722021-06-09 10:53:51 -0700327
328/**
329 * @brief Function convert transfer protocol from string param.
330 *
331 */
332inline std::optional<TransferProtocol> getTransferProtocolFromParam(
333 const std::optional<std::string>& transferProtocolType)
334{
335 if (transferProtocolType == std::nullopt)
Agata Olenderc6f4e012020-03-11 15:19:07 +0100336 {
Ed Tanous22db1722021-06-09 10:53:51 -0700337 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100338 }
339
Ed Tanous22db1722021-06-09 10:53:51 -0700340 if (*transferProtocolType == "CIFS")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200341 {
Ed Tanous22db1722021-06-09 10:53:51 -0700342 return TransferProtocol::smb;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200343 }
344
Ed Tanous22db1722021-06-09 10:53:51 -0700345 if (*transferProtocolType == "HTTPS")
346 {
347 return TransferProtocol::https;
348 }
349
350 return TransferProtocol::invalid;
351}
352
353/**
354 * @brief Function extends URI with transfer protocol type.
355 *
356 */
357inline std::string
358 getUriWithTransferProtocol(const std::string& imageUri,
359 const TransferProtocol& transferProtocol)
360{
361 if (transferProtocol == TransferProtocol::smb)
362 {
363 return "smb://" + imageUri;
364 }
365
366 if (transferProtocol == TransferProtocol::https)
367 {
368 return "https://" + imageUri;
369 }
370
371 return imageUri;
372}
373
374/**
375 * @brief Function validate parameters of insert media request.
376 *
377 */
378inline bool
379 validateParams(crow::Response& res, std::string& imageUrl,
380 const std::optional<bool>& inserted,
381 const std::optional<std::string>& transferMethod,
382 const std::optional<std::string>& transferProtocolType)
383{
384 BMCWEB_LOG_DEBUG << "Validation started";
385 // required param imageUrl must not be empty
386 if (imageUrl.empty())
387 {
388 BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
389
390 messages::propertyValueFormatError(res, "<empty>", "Image");
391
392 return false;
393 }
394
395 // optional param inserted must be true
Ed Tanouse05aec52022-01-25 10:28:56 -0800396 if ((inserted != std::nullopt) && !*inserted)
Ed Tanous22db1722021-06-09 10:53:51 -0700397 {
398 BMCWEB_LOG_ERROR
399 << "Request action optional parameter Inserted must be true.";
400
401 messages::actionParameterNotSupported(res, "Inserted", "InsertMedia");
402
403 return false;
404 }
405
406 // optional param transferMethod must be stream
407 if ((transferMethod != std::nullopt) && (*transferMethod != "Stream"))
408 {
409 BMCWEB_LOG_ERROR << "Request action optional parameter "
410 "TransferMethod must be Stream.";
411
412 messages::actionParameterNotSupported(res, "TransferMethod",
413 "InsertMedia");
414
415 return false;
416 }
Ed Tanousace85d62021-10-26 12:45:59 -0700417 boost::urls::result<boost::urls::url_view> url =
418 boost::urls::parse_uri(boost::string_view(imageUrl));
419 if (!url)
420 {
421 messages::resourceAtUriInUnknownFormat(res, *url);
422 return {};
423 }
Ed Tanous22db1722021-06-09 10:53:51 -0700424 std::optional<TransferProtocol> uriTransferProtocolType =
Ed Tanousace85d62021-10-26 12:45:59 -0700425 getTransferProtocolFromUri(*url);
Ed Tanous22db1722021-06-09 10:53:51 -0700426
427 std::optional<TransferProtocol> paramTransferProtocolType =
428 getTransferProtocolFromParam(transferProtocolType);
429
430 // ImageUrl does not contain valid protocol type
431 if (*uriTransferProtocolType == TransferProtocol::invalid)
432 {
433 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
434 "contain specified protocol type from list: "
435 "(smb, https).";
436
Ed Tanousace85d62021-10-26 12:45:59 -0700437 messages::resourceAtUriInUnknownFormat(res, *url);
Ed Tanous22db1722021-06-09 10:53:51 -0700438
439 return false;
440 }
441
442 // transferProtocolType should contain value from list
443 if (*paramTransferProtocolType == TransferProtocol::invalid)
444 {
445 BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
446 "must be provided with value from list: "
447 "(CIFS, HTTPS).";
448
449 messages::propertyValueNotInList(res, *transferProtocolType,
450 "TransferProtocolType");
451 return false;
452 }
453
454 // valid transfer protocol not provided either with URI nor param
455 if ((uriTransferProtocolType == std::nullopt) &&
456 (paramTransferProtocolType == std::nullopt))
457 {
458 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
459 "contain specified protocol type or param "
460 "TransferProtocolType must be provided.";
461
Ed Tanousace85d62021-10-26 12:45:59 -0700462 messages::resourceAtUriInUnknownFormat(res, *url);
Ed Tanous22db1722021-06-09 10:53:51 -0700463
464 return false;
465 }
466
467 // valid transfer protocol provided both with URI and param
468 if ((paramTransferProtocolType != std::nullopt) &&
469 (uriTransferProtocolType != std::nullopt))
470 {
471 // check if protocol is the same for URI and param
472 if (*paramTransferProtocolType != *uriTransferProtocolType)
473 {
474 BMCWEB_LOG_ERROR << "Request action parameter "
475 "TransferProtocolType must contain the "
476 "same protocol type as protocol type "
477 "provided with param imageUrl.";
478
479 messages::actionParameterValueTypeError(res, *transferProtocolType,
480 "TransferProtocolType",
481 "InsertMedia");
482
483 return false;
484 }
485 }
486
487 // validation passed
488 // add protocol to URI if needed
489 if (uriTransferProtocolType == std::nullopt)
490 {
491 imageUrl =
492 getUriWithTransferProtocol(imageUrl, *paramTransferProtocolType);
493 }
494
495 return true;
496}
497
498template <typename T>
499static void secureCleanup(T& value)
500{
Ed Tanous4ecc6182022-01-07 09:36:26 -0800501 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
Ed Tanous22db1722021-06-09 10:53:51 -0700502 auto raw = const_cast<typename T::value_type*>(value.data());
503 explicit_bzero(raw, value.size() * sizeof(*raw));
504}
505
506class Credentials
507{
508 public:
509 Credentials(std::string&& user, std::string&& password) :
510 userBuf(std::move(user)), passBuf(std::move(password))
511 {}
512
513 ~Credentials()
514 {
515 secureCleanup(userBuf);
516 secureCleanup(passBuf);
517 }
518
519 const std::string& user()
520 {
521 return userBuf;
522 }
523
524 const std::string& password()
525 {
526 return passBuf;
527 }
528
529 Credentials() = delete;
530 Credentials(const Credentials&) = delete;
531 Credentials& operator=(const Credentials&) = delete;
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800532 Credentials(Credentials&&) = delete;
533 Credentials& operator=(Credentials&&) = delete;
Ed Tanous22db1722021-06-09 10:53:51 -0700534
535 private:
536 std::string userBuf;
537 std::string passBuf;
538};
539
540class CredentialsProvider
541{
542 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500543 template <typename T>
Ed Tanous22db1722021-06-09 10:53:51 -0700544 struct Deleter
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100545 {
Ed Tanous22db1722021-06-09 10:53:51 -0700546 void operator()(T* buff) const
547 {
548 if (buff)
549 {
550 secureCleanup(*buff);
551 delete buff;
552 }
553 }
554 };
555
556 using Buffer = std::vector<char>;
557 using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
558 // Using explicit definition instead of std::function to avoid implicit
559 // conversions eg. stack copy instead of reference
560 using FormatterFunc = void(const std::string& username,
561 const std::string& password, Buffer& dest);
562
563 CredentialsProvider(std::string&& user, std::string&& password) :
564 credentials(std::move(user), std::move(password))
565 {}
566
567 const std::string& user()
568 {
569 return credentials.user();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100570 }
571
Ed Tanous22db1722021-06-09 10:53:51 -0700572 const std::string& password()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100573 {
Ed Tanous22db1722021-06-09 10:53:51 -0700574 return credentials.password();
575 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100576
Ed Tanous22db1722021-06-09 10:53:51 -0700577 SecureBuffer pack(FormatterFunc formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100578 {
Ed Tanous22db1722021-06-09 10:53:51 -0700579 SecureBuffer packed{new Buffer{}};
Ed Tanouse662eae2022-01-25 10:39:19 -0800580 if (formatter != nullptr)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100581 {
Ed Tanous22db1722021-06-09 10:53:51 -0700582 formatter(credentials.user(), credentials.password(), *packed);
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100583 }
584
Ed Tanous22db1722021-06-09 10:53:51 -0700585 return packed;
586 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100587
Ed Tanous22db1722021-06-09 10:53:51 -0700588 private:
589 Credentials credentials;
590};
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100591
Ed Tanous22db1722021-06-09 10:53:51 -0700592// Wrapper for boost::async_pipe ensuring proper pipe cleanup
593template <typename Buffer>
594class Pipe
595{
596 public:
597 using unix_fd = sdbusplus::message::unix_fd;
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100598
Ed Tanous22db1722021-06-09 10:53:51 -0700599 Pipe(boost::asio::io_context& io, Buffer&& buffer) :
600 impl(io), buffer{std::move(buffer)}
601 {}
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100602
Ed Tanous22db1722021-06-09 10:53:51 -0700603 ~Pipe()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100604 {
Ed Tanous22db1722021-06-09 10:53:51 -0700605 // Named pipe needs to be explicitly removed
606 impl.close();
607 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100608
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800609 Pipe(const Pipe&) = delete;
610 Pipe(Pipe&&) = delete;
611 Pipe& operator=(const Pipe&) = delete;
612 Pipe& operator=(Pipe&&) = delete;
613
Ed Tanous22db1722021-06-09 10:53:51 -0700614 unix_fd fd()
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200615 {
Ed Tanous22db1722021-06-09 10:53:51 -0700616 return unix_fd{impl.native_source()};
617 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100618
Ed Tanous22db1722021-06-09 10:53:51 -0700619 template <typename WriteHandler>
620 void asyncWrite(WriteHandler&& handler)
621 {
622 impl.async_write_some(data(), std::forward<WriteHandler>(handler));
623 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100624
Ed Tanous22db1722021-06-09 10:53:51 -0700625 private:
626 // Specialization for pointer types
627 template <typename B = Buffer>
628 typename std::enable_if<boost::has_dereference<B>::value,
629 boost::asio::const_buffer>::type
630 data()
631 {
632 return boost::asio::buffer(*buffer);
633 }
634
635 template <typename B = Buffer>
636 typename std::enable_if<!boost::has_dereference<B>::value,
637 boost::asio::const_buffer>::type
638 data()
639 {
640 return boost::asio::buffer(buffer);
641 }
642
643 const std::string name;
644 boost::process::async_pipe impl;
645 Buffer buffer;
646};
647
648/**
649 * @brief Function transceives data with dbus directly.
650 *
651 * All BMC state properties will be retrieved before sending reset request.
652 */
653inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
654 const std::string& service, const std::string& name,
655 const std::string& imageUrl, const bool rw,
656 std::string&& userName, std::string&& password)
657{
658 using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
659 constexpr const size_t secretLimit = 1024;
660
661 std::shared_ptr<SecurePipe> secretPipe;
Ed Tanous168e20c2021-12-13 14:39:53 -0800662 dbus::utility::DbusVariantType unixFd = -1;
Ed Tanous22db1722021-06-09 10:53:51 -0700663
664 if (!userName.empty() || !password.empty())
665 {
666 // Encapsulate in safe buffer
667 CredentialsProvider credentials(std::move(userName),
668 std::move(password));
669
670 // Payload must contain data + NULL delimiters
671 if (credentials.user().size() + credentials.password().size() + 2 >
672 secretLimit)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100673 {
Ed Tanous22db1722021-06-09 10:53:51 -0700674 BMCWEB_LOG_ERROR << "Credentials too long to handle";
675 messages::unrecognizedRequestBody(asyncResp->res);
676 return;
677 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100678
Ed Tanous22db1722021-06-09 10:53:51 -0700679 // Pack secret
680 auto secret = credentials.pack(
681 [](const auto& user, const auto& pass, auto& buff) {
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100682 std::copy(user.begin(), user.end(), std::back_inserter(buff));
683 buff.push_back('\0');
684 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
685 buff.push_back('\0');
686 });
687
Ed Tanous22db1722021-06-09 10:53:51 -0700688 // Open pipe
689 secretPipe = std::make_shared<SecurePipe>(
690 crow::connections::systemBus->get_io_context(), std::move(secret));
691 unixFd = secretPipe->fd();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100692
Ed Tanous22db1722021-06-09 10:53:51 -0700693 // Pass secret over pipe
694 secretPipe->asyncWrite(
695 [asyncResp](const boost::system::error_code& ec, std::size_t) {
696 if (ec)
697 {
698 BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
699 messages::internalError(asyncResp->res);
700 }
701 });
702 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100703
Ed Tanous22db1722021-06-09 10:53:51 -0700704 crow::connections::systemBus->async_method_call(
705 [asyncResp, secretPipe](const boost::system::error_code ec,
706 bool success) {
707 if (ec)
708 {
709 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
710 messages::internalError(asyncResp->res);
711 }
712 else if (!success)
713 {
714 BMCWEB_LOG_ERROR << "Service responded with error";
715 messages::generalError(asyncResp->res);
716 }
717 },
718 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
719 "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
720 unixFd);
721}
722
723/**
724 * @brief Function transceives data with dbus directly.
725 *
726 * All BMC state properties will be retrieved before sending reset request.
727 */
728inline void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
729 const std::string& service, const std::string& name,
730 bool legacy)
731{
732
733 // Legacy mount requires parameter with image
734 if (legacy)
735 {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100736 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700737 [asyncResp](const boost::system::error_code ec) {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100738 if (ec)
739 {
740 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700741
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100742 messages::internalError(asyncResp->res);
Ed Tanous22db1722021-06-09 10:53:51 -0700743 return;
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100744 }
745 },
746 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
Ed Tanous22db1722021-06-09 10:53:51 -0700747 "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200748 }
Ed Tanous22db1722021-06-09 10:53:51 -0700749 else // proxy
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200750 {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200751 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700752 [asyncResp](const boost::system::error_code ec) {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200753 if (ec)
754 {
Ed Tanous22db1722021-06-09 10:53:51 -0700755 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
756
zhanghch058d1b46d2021-04-01 11:18:24 +0800757 messages::internalError(asyncResp->res);
Ed Tanous22db1722021-06-09 10:53:51 -0700758 return;
759 }
760 },
761 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
762 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
763 }
764}
765
Ed Tanous98be3e32021-09-16 15:05:36 -0700766struct InsertMediaActionParams
767{
768 std::string imageUrl;
769 std::optional<std::string> userName;
770 std::optional<std::string> password;
771 std::optional<std::string> transferMethod;
772 std::optional<std::string> transferProtocolType;
773 std::optional<bool> writeProtected = true;
774 std::optional<bool> inserted;
775};
776
Ed Tanous22db1722021-06-09 10:53:51 -0700777inline void requestNBDVirtualMediaRoutes(App& app)
778{
George Liu0fda0f12021-11-16 10:06:17 +0800779 BMCWEB_ROUTE(
780 app,
781 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
Ed Tanoused398212021-06-09 17:05:54 -0700782 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -0700783 .methods(boost::beast::http::verb::post)(
784 [](const crow::Request& req,
785 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
786 const std::string& name, const std::string& resName) {
787 if (name != "bmc")
788 {
789 messages::resourceNotFound(asyncResp->res,
790 "VirtualMedia.Insert", resName);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200791
792 return;
793 }
Ed Tanous98be3e32021-09-16 15:05:36 -0700794 InsertMediaActionParams actionParams;
795
796 // Read obligatory parameters (url of
797 // image)
Willy Tu15ed6782021-12-14 11:03:16 -0800798 if (!json_util::readJsonAction(
Ed Tanous98be3e32021-09-16 15:05:36 -0700799 req, asyncResp->res, "Image", actionParams.imageUrl,
800 "WriteProtected", actionParams.writeProtected,
801 "UserName", actionParams.userName, "Password",
802 actionParams.password, "Inserted",
803 actionParams.inserted, "TransferMethod",
804 actionParams.transferMethod, "TransferProtocolType",
805 actionParams.transferProtocolType))
806 {
807 BMCWEB_LOG_DEBUG << "Image is not provided";
808 return;
809 }
810
811 bool paramsValid = validateParams(
812 asyncResp->res, actionParams.imageUrl,
813 actionParams.inserted, actionParams.transferMethod,
814 actionParams.transferProtocolType);
815
Ed Tanouse05aec52022-01-25 10:28:56 -0800816 if (!paramsValid)
Ed Tanous98be3e32021-09-16 15:05:36 -0700817 {
818 return;
819 }
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200820
821 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700822 [asyncResp, actionParams,
Ed Tanous22db1722021-06-09 10:53:51 -0700823 resName](const boost::system::error_code ec,
Ed Tanous98be3e32021-09-16 15:05:36 -0700824 const GetObjectType& getObjectType) mutable {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200825 if (ec)
826 {
Ed Tanous22db1722021-06-09 10:53:51 -0700827 BMCWEB_LOG_ERROR
828 << "ObjectMapper::GetObject call failed: "
829 << ec;
830 messages::internalError(asyncResp->res);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200831
832 return;
833 }
Ed Tanous22db1722021-06-09 10:53:51 -0700834 std::string service = getObjectType.begin()->first;
835 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200836
Ed Tanous22db1722021-06-09 10:53:51 -0700837 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700838 [service, resName, actionParams,
Ed Tanous22db1722021-06-09 10:53:51 -0700839 asyncResp](const boost::system::error_code ec,
Ed Tanous711ac7a2021-12-20 09:34:41 -0800840 dbus::utility::ManagedObjectType&
841 subtree) mutable {
Ed Tanous22db1722021-06-09 10:53:51 -0700842 if (ec)
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200843 {
Ed Tanous22db1722021-06-09 10:53:51 -0700844 BMCWEB_LOG_DEBUG << "DBUS response error";
845
846 return;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200847 }
848
Ed Tanous22db1722021-06-09 10:53:51 -0700849 for (const auto& object : subtree)
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200850 {
Ed Tanous22db1722021-06-09 10:53:51 -0700851 const std::string& path =
852 static_cast<const std::string&>(
853 object.first);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200854
Ed Tanous22db1722021-06-09 10:53:51 -0700855 std::size_t lastIndex = path.rfind('/');
856 if (lastIndex == std::string::npos)
857 {
858 continue;
859 }
860
861 lastIndex += 1;
862
863 if (path.substr(lastIndex) == resName)
864 {
865 lastIndex = path.rfind("Proxy");
866 if (lastIndex != std::string::npos)
867 {
868 // Not possible in proxy mode
869 BMCWEB_LOG_DEBUG
870 << "InsertMedia not "
871 "allowed in proxy mode";
872 messages::resourceNotFound(
873 asyncResp->res,
874 "VirtualMedia.InsertMedia",
875 resName);
876
877 return;
878 }
879
880 lastIndex = path.rfind("Legacy");
881 if (lastIndex == std::string::npos)
882 {
883 continue;
884 }
885
Ed Tanous22db1722021-06-09 10:53:51 -0700886 // manager is irrelevant for
887 // VirtualMedia dbus calls
Ed Tanous98be3e32021-09-16 15:05:36 -0700888 doMountVmLegacy(
889 asyncResp, service, resName,
890 actionParams.imageUrl,
891 !(*actionParams.writeProtected),
892 std::move(*actionParams.userName),
893 std::move(*actionParams.password));
Ed Tanous22db1722021-06-09 10:53:51 -0700894
895 return;
896 }
897 }
898 BMCWEB_LOG_DEBUG << "Parent item not found";
899 messages::resourceNotFound(
900 asyncResp->res, "VirtualMedia", resName);
901 },
902 service, "/xyz/openbmc_project/VirtualMedia",
903 "org.freedesktop.DBus.ObjectManager",
904 "GetManagedObjects");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200905 },
Ed Tanous22db1722021-06-09 10:53:51 -0700906 "xyz.openbmc_project.ObjectMapper",
907 "/xyz/openbmc_project/object_mapper",
908 "xyz.openbmc_project.ObjectMapper", "GetObject",
909 "/xyz/openbmc_project/VirtualMedia",
910 std::array<const char*, 0>());
911 });
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200912
George Liu0fda0f12021-11-16 10:06:17 +0800913 BMCWEB_ROUTE(
914 app,
915 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
Ed Tanoused398212021-06-09 17:05:54 -0700916 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -0700917 .methods(boost::beast::http::verb::post)(
Ed Tanous98be3e32021-09-16 15:05:36 -0700918 [](const crow::Request&,
Ed Tanous22db1722021-06-09 10:53:51 -0700919 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
920 const std::string& name, const std::string& resName) {
921 if (name != "bmc")
922 {
923 messages::resourceNotFound(asyncResp->res,
924 "VirtualMedia.Eject", resName);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200925
Ed Tanous22db1722021-06-09 10:53:51 -0700926 return;
927 }
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200928
Ed Tanous22db1722021-06-09 10:53:51 -0700929 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700930 [asyncResp, resName](const boost::system::error_code ec,
931 const GetObjectType& getObjectType) {
Ed Tanous22db1722021-06-09 10:53:51 -0700932 if (ec)
933 {
934 BMCWEB_LOG_ERROR
935 << "ObjectMapper::GetObject call failed: "
936 << ec;
937 messages::internalError(asyncResp->res);
938
939 return;
940 }
941 std::string service = getObjectType.begin()->first;
942 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
943
944 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700945 [resName, service, asyncResp{asyncResp}](
Ed Tanous22db1722021-06-09 10:53:51 -0700946 const boost::system::error_code ec,
Ed Tanous711ac7a2021-12-20 09:34:41 -0800947 dbus::utility::ManagedObjectType& subtree) {
Ed Tanous22db1722021-06-09 10:53:51 -0700948 if (ec)
949 {
950 BMCWEB_LOG_DEBUG << "DBUS response error";
951
952 return;
953 }
954
955 for (const auto& object : subtree)
956 {
957 const std::string& path =
958 static_cast<const std::string&>(
959 object.first);
960
961 std::size_t lastIndex = path.rfind('/');
962 if (lastIndex == std::string::npos)
963 {
964 continue;
965 }
966
967 lastIndex += 1;
968
969 if (path.substr(lastIndex) == resName)
970 {
971 lastIndex = path.rfind("Proxy");
972 if (lastIndex != std::string::npos)
973 {
974 // Proxy mode
975 doVmAction(asyncResp, service,
976 resName, false);
977 }
978
979 lastIndex = path.rfind("Legacy");
980 if (lastIndex != std::string::npos)
981 {
982 // Legacy mode
983 doVmAction(asyncResp, service,
984 resName, true);
985 }
986
987 return;
988 }
989 }
990 BMCWEB_LOG_DEBUG << "Parent item not found";
991 messages::resourceNotFound(
992 asyncResp->res, "VirtualMedia", resName);
993 },
994 service, "/xyz/openbmc_project/VirtualMedia",
995 "org.freedesktop.DBus.ObjectManager",
996 "GetManagedObjects");
997 },
998 "xyz.openbmc_project.ObjectMapper",
999 "/xyz/openbmc_project/object_mapper",
1000 "xyz.openbmc_project.ObjectMapper", "GetObject",
1001 "/xyz/openbmc_project/VirtualMedia",
1002 std::array<const char*, 0>());
1003 });
1004 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
Ed Tanoused398212021-06-09 17:05:54 -07001005 .privileges(redfish::privileges::getVirtualMediaCollection)
Ed Tanous22db1722021-06-09 10:53:51 -07001006 .methods(boost::beast::http::verb::get)(
1007 [](const crow::Request& /* req */,
1008 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1009 const std::string& name) {
1010 if (name != "bmc")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001011 {
Ed Tanous22db1722021-06-09 10:53:51 -07001012 messages::resourceNotFound(asyncResp->res, "VirtualMedia",
1013 name);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001014
1015 return;
1016 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001017
Ed Tanous22db1722021-06-09 10:53:51 -07001018 asyncResp->res.jsonValue["@odata.type"] =
1019 "#VirtualMediaCollection.VirtualMediaCollection";
1020 asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
1021 asyncResp->res.jsonValue["@odata.id"] =
1022 "/redfish/v1/Managers/" + name + "/VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001023
Ed Tanous22db1722021-06-09 10:53:51 -07001024 crow::connections::systemBus->async_method_call(
1025 [asyncResp, name](const boost::system::error_code ec,
1026 const GetObjectType& getObjectType) {
1027 if (ec)
1028 {
1029 BMCWEB_LOG_ERROR
1030 << "ObjectMapper::GetObject call failed: "
1031 << ec;
1032 messages::internalError(asyncResp->res);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001033
Ed Tanous22db1722021-06-09 10:53:51 -07001034 return;
1035 }
1036 std::string service = getObjectType.begin()->first;
1037 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001038
Ed Tanous22db1722021-06-09 10:53:51 -07001039 getVmResourceList(asyncResp, service, name);
1040 },
1041 "xyz.openbmc_project.ObjectMapper",
1042 "/xyz/openbmc_project/object_mapper",
1043 "xyz.openbmc_project.ObjectMapper", "GetObject",
1044 "/xyz/openbmc_project/VirtualMedia",
1045 std::array<const char*, 0>());
1046 });
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001047
Ed Tanous22db1722021-06-09 10:53:51 -07001048 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001049 .privileges(redfish::privileges::getVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -07001050 .methods(boost::beast::http::verb::get)(
1051 [](const crow::Request& /* req */,
1052 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1053 const std::string& name, const std::string& resName) {
1054 if (name != "bmc")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001055 {
Ed Tanous22db1722021-06-09 10:53:51 -07001056 messages::resourceNotFound(asyncResp->res, "VirtualMedia",
1057 resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001058
1059 return;
1060 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001061
Ed Tanous22db1722021-06-09 10:53:51 -07001062 crow::connections::systemBus->async_method_call(
1063 [asyncResp, name,
1064 resName](const boost::system::error_code ec,
1065 const GetObjectType& getObjectType) {
1066 if (ec)
1067 {
1068 BMCWEB_LOG_ERROR
1069 << "ObjectMapper::GetObject call failed: "
1070 << ec;
1071 messages::internalError(asyncResp->res);
1072
1073 return;
1074 }
1075 std::string service = getObjectType.begin()->first;
1076 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1077
1078 getVmData(asyncResp, service, name, resName);
1079 },
1080 "xyz.openbmc_project.ObjectMapper",
1081 "/xyz/openbmc_project/object_mapper",
1082 "xyz.openbmc_project.ObjectMapper", "GetObject",
1083 "/xyz/openbmc_project/VirtualMedia",
1084 std::array<const char*, 0>());
1085 });
1086}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001087
1088} // namespace redfish