blob: 844b60d862560ca4ec18b896538ec07a023b5866 [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 Tanous22db1722021-06-09 10:53:51 -070034inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
Anna Platash9e319cf2020-11-17 10:18:31 +010035{
Ed Tanousd32c4fa2021-09-14 13:16:51 -070036 boost::urls::error_code ec;
37 boost::urls::url_view url =
38 boost::urls::parse_uri(boost::string_view(imageUri), ec);
39 if (ec)
Anna Platash9e319cf2020-11-17 10:18:31 +010040 {
Ed Tanousd32c4fa2021-09-14 13:16:51 -070041 return "None";
Anna Platash9e319cf2020-11-17 10:18:31 +010042 }
Ed Tanousd32c4fa2021-09-14 13:16:51 -070043 boost::string_view scheme = url.scheme();
44 if (scheme == "smb")
Anna Platash9e319cf2020-11-17 10:18:31 +010045 {
Ed Tanousd32c4fa2021-09-14 13:16:51 -070046 return "CIFS";
Anna Platash9e319cf2020-11-17 10:18:31 +010047 }
Ed Tanousd32c4fa2021-09-14 13:16:51 -070048 if (scheme == "https")
49 {
50 return "HTTPS";
51 }
52
Anna Platash9e319cf2020-11-17 10:18:31 +010053 return "None";
54}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020055
56/**
57 * @brief Read all known properties from VM object interfaces
58 */
Ed Tanous22db1722021-06-09 10:53:51 -070059inline void
Ed Tanous711ac7a2021-12-20 09:34:41 -080060 vmParseInterfaceObject(const dbus::utility::DBusInteracesMap& interface,
zhanghch058d1b46d2021-04-01 11:18:24 +080061 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020062{
Ed Tanous711ac7a2021-12-20 09:34:41 -080063 for (const auto& [interface, values] : interface)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020064 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080065 if (interface == "xyz.openbmc_project.VirtualMedia.MountPoint")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020066 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080067 for (const auto& [property, value] : values)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020068 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080069 if (property == "EndpointId")
70 {
71 const std::string* endpointIdValue =
72 std::get_if<std::string>(&value);
73 if (endpointIdValue == nullptr)
74 {
75 continue;
76 }
77 if (!endpointIdValue->empty())
78 {
79 // Proxy mode
80 aResp->res
81 .jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
82 *endpointIdValue;
83 aResp->res.jsonValue["TransferProtocolType"] = "OEM";
84 }
85 }
86 if (property == "ImageURL")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020087 {
Anna Platash9e319cf2020-11-17 10:18:31 +010088 const std::string* imageUrlValue =
Ed Tanous711ac7a2021-12-20 09:34:41 -080089 std::get_if<std::string>(&value);
Anna Platash9e319cf2020-11-17 10:18:31 +010090 if (imageUrlValue && !imageUrlValue->empty())
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +010091 {
Anna Platash9e319cf2020-11-17 10:18:31 +010092 std::filesystem::path filePath = *imageUrlValue;
93 if (!filePath.has_filename())
94 {
95 // this will handle https share, which not
96 // necessarily has to have filename given.
97 aResp->res.jsonValue["ImageName"] = "";
98 }
99 else
100 {
101 aResp->res.jsonValue["ImageName"] =
102 filePath.filename();
103 }
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100104
Anna Platash9e319cf2020-11-17 10:18:31 +0100105 aResp->res.jsonValue["Image"] = *imageUrlValue;
Anna Platash9e319cf2020-11-17 10:18:31 +0100106 aResp->res.jsonValue["TransferProtocolType"] =
107 getTransferProtocolTypeFromUri(*imageUrlValue);
108
Ed Tanous711ac7a2021-12-20 09:34:41 -0800109 aResp->res.jsonValue["ConnectedVia"] = "URI";
Anna Platash9e319cf2020-11-17 10:18:31 +0100110 }
111 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800112 if (property == "WriteProtected")
Anna Platash9e319cf2020-11-17 10:18:31 +0100113 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800114 const bool* writeProtectedValue = std::get_if<bool>(&value);
Anna Platash9e319cf2020-11-17 10:18:31 +0100115 if (writeProtectedValue)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200116 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100117 aResp->res.jsonValue["WriteProtected"] =
118 *writeProtectedValue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200119 }
120 }
121 }
122 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800123 if (interface == "xyz.openbmc_project.VirtualMedia.Process")
124 {
125 for (const auto& [property, value] : values)
126 {
127 if (property == "Active")
128 {
129 const bool* activeValue = std::get_if<bool>(&value);
130 if (!activeValue)
131 {
132 BMCWEB_LOG_DEBUG << "Value Active not found";
133 return;
134 }
135 aResp->res.jsonValue["Inserted"] = *activeValue;
136
137 if (*activeValue == true)
138 {
139 aResp->res.jsonValue["ConnectedVia"] = "Applet";
140 }
141 }
142 }
143 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200144 }
145}
146
147/**
148 * @brief Fill template for Virtual Media Item.
149 */
Ed Tanous22db1722021-06-09 10:53:51 -0700150inline nlohmann::json vmItemTemplate(const std::string& name,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500151 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200152{
153 nlohmann::json item;
Ed Tanous22db1722021-06-09 10:53:51 -0700154
155 std::string id = "/redfish/v1/Managers/";
156 id += name;
157 id += "/VirtualMedia/";
158 id += resName;
159 item["@odata.id"] = std::move(id);
160
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100161 item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200162 item["Name"] = "Virtual Removable Media";
163 item["Id"] = resName;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200164 item["WriteProtected"] = true;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200165 item["MediaTypes"] = {"CD", "USBStick"};
166 item["TransferMethod"] = "Stream";
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100167 item["Oem"]["OpenBMC"]["@odata.type"] =
168 "#OemVirtualMedia.v1_0_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200169
170 return item;
171}
172
173/**
174 * @brief Fills collection data
175 */
Ed Tanous22db1722021-06-09 10:53:51 -0700176inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500177 const std::string& service,
178 const std::string& name)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200179{
180 BMCWEB_LOG_DEBUG << "Get available Virtual Media resources.";
181 crow::connections::systemBus->async_method_call(
Ed Tanous711ac7a2021-12-20 09:34:41 -0800182 [name,
183 aResp{std::move(aResp)}](const boost::system::error_code ec,
184 dbus::utility::ManagedObjectType& subtree) {
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200185 if (ec)
186 {
187 BMCWEB_LOG_DEBUG << "DBUS response error";
188 return;
189 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500190 nlohmann::json& members = aResp->res.jsonValue["Members"];
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200191 members = nlohmann::json::array();
192
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500193 for (const auto& object : subtree)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200194 {
195 nlohmann::json item;
Ed Tanous2dfd18e2020-12-18 00:41:31 +0000196 std::string path = object.first.filename();
197 if (path.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200198 {
199 continue;
200 }
201
Ed Tanous22db1722021-06-09 10:53:51 -0700202 std::string id = "/redfish/v1/Managers/";
203 id += name;
204 id += "/VirtualMedia/";
205 id += path;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200206
Ed Tanous22db1722021-06-09 10:53:51 -0700207 item["@odata.id"] = std::move(id);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200208 members.emplace_back(std::move(item));
209 }
210 aResp->res.jsonValue["Members@odata.count"] = members.size();
211 },
212 service, "/xyz/openbmc_project/VirtualMedia",
213 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
214}
215
216/**
217 * @brief Fills data for specific resource
218 */
Ed Tanous22db1722021-06-09 10:53:51 -0700219inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500220 const std::string& service, const std::string& name,
221 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200222{
223 BMCWEB_LOG_DEBUG << "Get Virtual Media resource data.";
224
225 crow::connections::systemBus->async_method_call(
226 [resName, name, aResp](const boost::system::error_code ec,
Ed Tanous711ac7a2021-12-20 09:34:41 -0800227 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
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500235 for (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 */
308inline std::optional<TransferProtocol>
309 getTransferProtocolFromUri(const std::string& imageUri)
310{
Ed Tanousd32c4fa2021-09-14 13:16:51 -0700311 boost::urls::error_code ec;
312 boost::urls::url_view url =
313 boost::urls::parse_uri(boost::string_view(imageUri), ec);
314 if (ec)
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200315 {
Ed Tanousd32c4fa2021-09-14 13:16:51 -0700316 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100317 }
Ed Tanousd32c4fa2021-09-14 13:16:51 -0700318
319 boost::string_view scheme = url.scheme();
320 if (scheme == "smb")
Agata Olenderc6f4e012020-03-11 15:19:07 +0100321 {
Ed Tanousd32c4fa2021-09-14 13:16:51 -0700322 return TransferProtocol::smb;
323 }
324 if (scheme == "https")
325 {
326 return TransferProtocol::https;
327 }
328 if (!scheme.empty())
329 {
330 return TransferProtocol::invalid;
Agata Olenderc6f4e012020-03-11 15:19:07 +0100331 }
332
Ed Tanous22db1722021-06-09 10:53:51 -0700333 return {};
334}
335
336/**
337 * @brief Function convert transfer protocol from string param.
338 *
339 */
340inline std::optional<TransferProtocol> getTransferProtocolFromParam(
341 const std::optional<std::string>& transferProtocolType)
342{
343 if (transferProtocolType == std::nullopt)
Agata Olenderc6f4e012020-03-11 15:19:07 +0100344 {
Ed Tanous22db1722021-06-09 10:53:51 -0700345 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100346 }
347
Ed Tanous22db1722021-06-09 10:53:51 -0700348 if (*transferProtocolType == "CIFS")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200349 {
Ed Tanous22db1722021-06-09 10:53:51 -0700350 return TransferProtocol::smb;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200351 }
352
Ed Tanous22db1722021-06-09 10:53:51 -0700353 if (*transferProtocolType == "HTTPS")
354 {
355 return TransferProtocol::https;
356 }
357
358 return TransferProtocol::invalid;
359}
360
361/**
362 * @brief Function extends URI with transfer protocol type.
363 *
364 */
365inline std::string
366 getUriWithTransferProtocol(const std::string& imageUri,
367 const TransferProtocol& transferProtocol)
368{
369 if (transferProtocol == TransferProtocol::smb)
370 {
371 return "smb://" + imageUri;
372 }
373
374 if (transferProtocol == TransferProtocol::https)
375 {
376 return "https://" + imageUri;
377 }
378
379 return imageUri;
380}
381
382/**
383 * @brief Function validate parameters of insert media request.
384 *
385 */
386inline bool
387 validateParams(crow::Response& res, std::string& imageUrl,
388 const std::optional<bool>& inserted,
389 const std::optional<std::string>& transferMethod,
390 const std::optional<std::string>& transferProtocolType)
391{
392 BMCWEB_LOG_DEBUG << "Validation started";
393 // required param imageUrl must not be empty
394 if (imageUrl.empty())
395 {
396 BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
397
398 messages::propertyValueFormatError(res, "<empty>", "Image");
399
400 return false;
401 }
402
403 // optional param inserted must be true
404 if ((inserted != std::nullopt) && (*inserted != true))
405 {
406 BMCWEB_LOG_ERROR
407 << "Request action optional parameter Inserted must be true.";
408
409 messages::actionParameterNotSupported(res, "Inserted", "InsertMedia");
410
411 return false;
412 }
413
414 // optional param transferMethod must be stream
415 if ((transferMethod != std::nullopt) && (*transferMethod != "Stream"))
416 {
417 BMCWEB_LOG_ERROR << "Request action optional parameter "
418 "TransferMethod must be Stream.";
419
420 messages::actionParameterNotSupported(res, "TransferMethod",
421 "InsertMedia");
422
423 return false;
424 }
425
426 std::optional<TransferProtocol> uriTransferProtocolType =
427 getTransferProtocolFromUri(imageUrl);
428
429 std::optional<TransferProtocol> paramTransferProtocolType =
430 getTransferProtocolFromParam(transferProtocolType);
431
432 // ImageUrl does not contain valid protocol type
433 if (*uriTransferProtocolType == TransferProtocol::invalid)
434 {
435 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
436 "contain specified protocol type from list: "
437 "(smb, https).";
438
439 messages::resourceAtUriInUnknownFormat(res, imageUrl);
440
441 return false;
442 }
443
444 // transferProtocolType should contain value from list
445 if (*paramTransferProtocolType == TransferProtocol::invalid)
446 {
447 BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
448 "must be provided with value from list: "
449 "(CIFS, HTTPS).";
450
451 messages::propertyValueNotInList(res, *transferProtocolType,
452 "TransferProtocolType");
453 return false;
454 }
455
456 // valid transfer protocol not provided either with URI nor param
457 if ((uriTransferProtocolType == std::nullopt) &&
458 (paramTransferProtocolType == std::nullopt))
459 {
460 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
461 "contain specified protocol type or param "
462 "TransferProtocolType must be provided.";
463
464 messages::resourceAtUriInUnknownFormat(res, imageUrl);
465
466 return false;
467 }
468
469 // valid transfer protocol provided both with URI and param
470 if ((paramTransferProtocolType != std::nullopt) &&
471 (uriTransferProtocolType != std::nullopt))
472 {
473 // check if protocol is the same for URI and param
474 if (*paramTransferProtocolType != *uriTransferProtocolType)
475 {
476 BMCWEB_LOG_ERROR << "Request action parameter "
477 "TransferProtocolType must contain the "
478 "same protocol type as protocol type "
479 "provided with param imageUrl.";
480
481 messages::actionParameterValueTypeError(res, *transferProtocolType,
482 "TransferProtocolType",
483 "InsertMedia");
484
485 return false;
486 }
487 }
488
489 // validation passed
490 // add protocol to URI if needed
491 if (uriTransferProtocolType == std::nullopt)
492 {
493 imageUrl =
494 getUriWithTransferProtocol(imageUrl, *paramTransferProtocolType);
495 }
496
497 return true;
498}
499
500template <typename T>
501static void secureCleanup(T& value)
502{
503 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;
533
534 private:
535 std::string userBuf;
536 std::string passBuf;
537};
538
539class CredentialsProvider
540{
541 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500542 template <typename T>
Ed Tanous22db1722021-06-09 10:53:51 -0700543 struct Deleter
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100544 {
Ed Tanous22db1722021-06-09 10:53:51 -0700545 void operator()(T* buff) const
546 {
547 if (buff)
548 {
549 secureCleanup(*buff);
550 delete buff;
551 }
552 }
553 };
554
555 using Buffer = std::vector<char>;
556 using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
557 // Using explicit definition instead of std::function to avoid implicit
558 // conversions eg. stack copy instead of reference
559 using FormatterFunc = void(const std::string& username,
560 const std::string& password, Buffer& dest);
561
562 CredentialsProvider(std::string&& user, std::string&& password) :
563 credentials(std::move(user), std::move(password))
564 {}
565
566 const std::string& user()
567 {
568 return credentials.user();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100569 }
570
Ed Tanous22db1722021-06-09 10:53:51 -0700571 const std::string& password()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100572 {
Ed Tanous22db1722021-06-09 10:53:51 -0700573 return credentials.password();
574 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100575
Ed Tanous22db1722021-06-09 10:53:51 -0700576 SecureBuffer pack(FormatterFunc formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100577 {
Ed Tanous22db1722021-06-09 10:53:51 -0700578 SecureBuffer packed{new Buffer{}};
579 if (formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100580 {
Ed Tanous22db1722021-06-09 10:53:51 -0700581 formatter(credentials.user(), credentials.password(), *packed);
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100582 }
583
Ed Tanous22db1722021-06-09 10:53:51 -0700584 return packed;
585 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100586
Ed Tanous22db1722021-06-09 10:53:51 -0700587 private:
588 Credentials credentials;
589};
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100590
Ed Tanous22db1722021-06-09 10:53:51 -0700591// Wrapper for boost::async_pipe ensuring proper pipe cleanup
592template <typename Buffer>
593class Pipe
594{
595 public:
596 using unix_fd = sdbusplus::message::unix_fd;
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100597
Ed Tanous22db1722021-06-09 10:53:51 -0700598 Pipe(boost::asio::io_context& io, Buffer&& buffer) :
599 impl(io), buffer{std::move(buffer)}
600 {}
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100601
Ed Tanous22db1722021-06-09 10:53:51 -0700602 ~Pipe()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100603 {
Ed Tanous22db1722021-06-09 10:53:51 -0700604 // Named pipe needs to be explicitly removed
605 impl.close();
606 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100607
Ed Tanous22db1722021-06-09 10:53:51 -0700608 unix_fd fd()
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200609 {
Ed Tanous22db1722021-06-09 10:53:51 -0700610 return unix_fd{impl.native_source()};
611 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100612
Ed Tanous22db1722021-06-09 10:53:51 -0700613 template <typename WriteHandler>
614 void asyncWrite(WriteHandler&& handler)
615 {
616 impl.async_write_some(data(), std::forward<WriteHandler>(handler));
617 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100618
Ed Tanous22db1722021-06-09 10:53:51 -0700619 private:
620 // Specialization for pointer types
621 template <typename B = Buffer>
622 typename std::enable_if<boost::has_dereference<B>::value,
623 boost::asio::const_buffer>::type
624 data()
625 {
626 return boost::asio::buffer(*buffer);
627 }
628
629 template <typename B = Buffer>
630 typename std::enable_if<!boost::has_dereference<B>::value,
631 boost::asio::const_buffer>::type
632 data()
633 {
634 return boost::asio::buffer(buffer);
635 }
636
637 const std::string name;
638 boost::process::async_pipe impl;
639 Buffer buffer;
640};
641
642/**
643 * @brief Function transceives data with dbus directly.
644 *
645 * All BMC state properties will be retrieved before sending reset request.
646 */
647inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
648 const std::string& service, const std::string& name,
649 const std::string& imageUrl, const bool rw,
650 std::string&& userName, std::string&& password)
651{
652 using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
653 constexpr const size_t secretLimit = 1024;
654
655 std::shared_ptr<SecurePipe> secretPipe;
Ed Tanous168e20c2021-12-13 14:39:53 -0800656 dbus::utility::DbusVariantType unixFd = -1;
Ed Tanous22db1722021-06-09 10:53:51 -0700657
658 if (!userName.empty() || !password.empty())
659 {
660 // Encapsulate in safe buffer
661 CredentialsProvider credentials(std::move(userName),
662 std::move(password));
663
664 // Payload must contain data + NULL delimiters
665 if (credentials.user().size() + credentials.password().size() + 2 >
666 secretLimit)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100667 {
Ed Tanous22db1722021-06-09 10:53:51 -0700668 BMCWEB_LOG_ERROR << "Credentials too long to handle";
669 messages::unrecognizedRequestBody(asyncResp->res);
670 return;
671 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100672
Ed Tanous22db1722021-06-09 10:53:51 -0700673 // Pack secret
674 auto secret = credentials.pack(
675 [](const auto& user, const auto& pass, auto& buff) {
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100676 std::copy(user.begin(), user.end(), std::back_inserter(buff));
677 buff.push_back('\0');
678 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
679 buff.push_back('\0');
680 });
681
Ed Tanous22db1722021-06-09 10:53:51 -0700682 // Open pipe
683 secretPipe = std::make_shared<SecurePipe>(
684 crow::connections::systemBus->get_io_context(), std::move(secret));
685 unixFd = secretPipe->fd();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100686
Ed Tanous22db1722021-06-09 10:53:51 -0700687 // Pass secret over pipe
688 secretPipe->asyncWrite(
689 [asyncResp](const boost::system::error_code& ec, std::size_t) {
690 if (ec)
691 {
692 BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
693 messages::internalError(asyncResp->res);
694 }
695 });
696 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100697
Ed Tanous22db1722021-06-09 10:53:51 -0700698 crow::connections::systemBus->async_method_call(
699 [asyncResp, secretPipe](const boost::system::error_code ec,
700 bool success) {
701 if (ec)
702 {
703 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
704 messages::internalError(asyncResp->res);
705 }
706 else if (!success)
707 {
708 BMCWEB_LOG_ERROR << "Service responded with error";
709 messages::generalError(asyncResp->res);
710 }
711 },
712 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
713 "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
714 unixFd);
715}
716
717/**
718 * @brief Function transceives data with dbus directly.
719 *
720 * All BMC state properties will be retrieved before sending reset request.
721 */
722inline void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
723 const std::string& service, const std::string& name,
724 bool legacy)
725{
726
727 // Legacy mount requires parameter with image
728 if (legacy)
729 {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100730 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700731 [asyncResp](const boost::system::error_code ec) {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100732 if (ec)
733 {
734 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700735
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100736 messages::internalError(asyncResp->res);
Ed Tanous22db1722021-06-09 10:53:51 -0700737 return;
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100738 }
739 },
740 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
Ed Tanous22db1722021-06-09 10:53:51 -0700741 "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200742 }
Ed Tanous22db1722021-06-09 10:53:51 -0700743 else // proxy
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200744 {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200745 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700746 [asyncResp](const boost::system::error_code ec) {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200747 if (ec)
748 {
Ed Tanous22db1722021-06-09 10:53:51 -0700749 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
750
zhanghch058d1b46d2021-04-01 11:18:24 +0800751 messages::internalError(asyncResp->res);
Ed Tanous22db1722021-06-09 10:53:51 -0700752 return;
753 }
754 },
755 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
756 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
757 }
758}
759
Ed Tanous98be3e32021-09-16 15:05:36 -0700760struct InsertMediaActionParams
761{
762 std::string imageUrl;
763 std::optional<std::string> userName;
764 std::optional<std::string> password;
765 std::optional<std::string> transferMethod;
766 std::optional<std::string> transferProtocolType;
767 std::optional<bool> writeProtected = true;
768 std::optional<bool> inserted;
769};
770
Ed Tanous22db1722021-06-09 10:53:51 -0700771inline void requestNBDVirtualMediaRoutes(App& app)
772{
George Liu0fda0f12021-11-16 10:06:17 +0800773 BMCWEB_ROUTE(
774 app,
775 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
Ed Tanoused398212021-06-09 17:05:54 -0700776 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -0700777 .methods(boost::beast::http::verb::post)(
778 [](const crow::Request& req,
779 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
780 const std::string& name, const std::string& resName) {
781 if (name != "bmc")
782 {
783 messages::resourceNotFound(asyncResp->res,
784 "VirtualMedia.Insert", resName);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200785
786 return;
787 }
Ed Tanous98be3e32021-09-16 15:05:36 -0700788 InsertMediaActionParams actionParams;
789
790 // Read obligatory parameters (url of
791 // image)
792 if (!json_util::readJson(
793 req, asyncResp->res, "Image", actionParams.imageUrl,
794 "WriteProtected", actionParams.writeProtected,
795 "UserName", actionParams.userName, "Password",
796 actionParams.password, "Inserted",
797 actionParams.inserted, "TransferMethod",
798 actionParams.transferMethod, "TransferProtocolType",
799 actionParams.transferProtocolType))
800 {
801 BMCWEB_LOG_DEBUG << "Image is not provided";
802 return;
803 }
804
805 bool paramsValid = validateParams(
806 asyncResp->res, actionParams.imageUrl,
807 actionParams.inserted, actionParams.transferMethod,
808 actionParams.transferProtocolType);
809
810 if (paramsValid == false)
811 {
812 return;
813 }
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200814
815 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700816 [asyncResp, actionParams,
Ed Tanous22db1722021-06-09 10:53:51 -0700817 resName](const boost::system::error_code ec,
Ed Tanous98be3e32021-09-16 15:05:36 -0700818 const GetObjectType& getObjectType) mutable {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200819 if (ec)
820 {
Ed Tanous22db1722021-06-09 10:53:51 -0700821 BMCWEB_LOG_ERROR
822 << "ObjectMapper::GetObject call failed: "
823 << ec;
824 messages::internalError(asyncResp->res);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200825
826 return;
827 }
Ed Tanous22db1722021-06-09 10:53:51 -0700828 std::string service = getObjectType.begin()->first;
829 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200830
Ed Tanous22db1722021-06-09 10:53:51 -0700831 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700832 [service, resName, actionParams,
Ed Tanous22db1722021-06-09 10:53:51 -0700833 asyncResp](const boost::system::error_code ec,
Ed Tanous711ac7a2021-12-20 09:34:41 -0800834 dbus::utility::ManagedObjectType&
835 subtree) mutable {
Ed Tanous22db1722021-06-09 10:53:51 -0700836 if (ec)
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200837 {
Ed Tanous22db1722021-06-09 10:53:51 -0700838 BMCWEB_LOG_DEBUG << "DBUS response error";
839
840 return;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200841 }
842
Ed Tanous22db1722021-06-09 10:53:51 -0700843 for (const auto& object : subtree)
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200844 {
Ed Tanous22db1722021-06-09 10:53:51 -0700845 const std::string& path =
846 static_cast<const std::string&>(
847 object.first);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200848
Ed Tanous22db1722021-06-09 10:53:51 -0700849 std::size_t lastIndex = path.rfind('/');
850 if (lastIndex == std::string::npos)
851 {
852 continue;
853 }
854
855 lastIndex += 1;
856
857 if (path.substr(lastIndex) == resName)
858 {
859 lastIndex = path.rfind("Proxy");
860 if (lastIndex != std::string::npos)
861 {
862 // Not possible in proxy mode
863 BMCWEB_LOG_DEBUG
864 << "InsertMedia not "
865 "allowed in proxy mode";
866 messages::resourceNotFound(
867 asyncResp->res,
868 "VirtualMedia.InsertMedia",
869 resName);
870
871 return;
872 }
873
874 lastIndex = path.rfind("Legacy");
875 if (lastIndex == std::string::npos)
876 {
877 continue;
878 }
879
Ed Tanous22db1722021-06-09 10:53:51 -0700880 // manager is irrelevant for
881 // VirtualMedia dbus calls
Ed Tanous98be3e32021-09-16 15:05:36 -0700882 doMountVmLegacy(
883 asyncResp, service, resName,
884 actionParams.imageUrl,
885 !(*actionParams.writeProtected),
886 std::move(*actionParams.userName),
887 std::move(*actionParams.password));
Ed Tanous22db1722021-06-09 10:53:51 -0700888
889 return;
890 }
891 }
892 BMCWEB_LOG_DEBUG << "Parent item not found";
893 messages::resourceNotFound(
894 asyncResp->res, "VirtualMedia", resName);
895 },
896 service, "/xyz/openbmc_project/VirtualMedia",
897 "org.freedesktop.DBus.ObjectManager",
898 "GetManagedObjects");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200899 },
Ed Tanous22db1722021-06-09 10:53:51 -0700900 "xyz.openbmc_project.ObjectMapper",
901 "/xyz/openbmc_project/object_mapper",
902 "xyz.openbmc_project.ObjectMapper", "GetObject",
903 "/xyz/openbmc_project/VirtualMedia",
904 std::array<const char*, 0>());
905 });
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200906
George Liu0fda0f12021-11-16 10:06:17 +0800907 BMCWEB_ROUTE(
908 app,
909 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
Ed Tanoused398212021-06-09 17:05:54 -0700910 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -0700911 .methods(boost::beast::http::verb::post)(
Ed Tanous98be3e32021-09-16 15:05:36 -0700912 [](const crow::Request&,
Ed Tanous22db1722021-06-09 10:53:51 -0700913 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
914 const std::string& name, const std::string& resName) {
915 if (name != "bmc")
916 {
917 messages::resourceNotFound(asyncResp->res,
918 "VirtualMedia.Eject", resName);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200919
Ed Tanous22db1722021-06-09 10:53:51 -0700920 return;
921 }
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200922
Ed Tanous22db1722021-06-09 10:53:51 -0700923 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700924 [asyncResp, resName](const boost::system::error_code ec,
925 const GetObjectType& getObjectType) {
Ed Tanous22db1722021-06-09 10:53:51 -0700926 if (ec)
927 {
928 BMCWEB_LOG_ERROR
929 << "ObjectMapper::GetObject call failed: "
930 << ec;
931 messages::internalError(asyncResp->res);
932
933 return;
934 }
935 std::string service = getObjectType.begin()->first;
936 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
937
938 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700939 [resName, service, asyncResp{asyncResp}](
Ed Tanous22db1722021-06-09 10:53:51 -0700940 const boost::system::error_code ec,
Ed Tanous711ac7a2021-12-20 09:34:41 -0800941 dbus::utility::ManagedObjectType& subtree) {
Ed Tanous22db1722021-06-09 10:53:51 -0700942 if (ec)
943 {
944 BMCWEB_LOG_DEBUG << "DBUS response error";
945
946 return;
947 }
948
949 for (const auto& object : subtree)
950 {
951 const std::string& path =
952 static_cast<const std::string&>(
953 object.first);
954
955 std::size_t lastIndex = path.rfind('/');
956 if (lastIndex == std::string::npos)
957 {
958 continue;
959 }
960
961 lastIndex += 1;
962
963 if (path.substr(lastIndex) == resName)
964 {
965 lastIndex = path.rfind("Proxy");
966 if (lastIndex != std::string::npos)
967 {
968 // Proxy mode
969 doVmAction(asyncResp, service,
970 resName, false);
971 }
972
973 lastIndex = path.rfind("Legacy");
974 if (lastIndex != std::string::npos)
975 {
976 // Legacy mode
977 doVmAction(asyncResp, service,
978 resName, true);
979 }
980
981 return;
982 }
983 }
984 BMCWEB_LOG_DEBUG << "Parent item not found";
985 messages::resourceNotFound(
986 asyncResp->res, "VirtualMedia", resName);
987 },
988 service, "/xyz/openbmc_project/VirtualMedia",
989 "org.freedesktop.DBus.ObjectManager",
990 "GetManagedObjects");
991 },
992 "xyz.openbmc_project.ObjectMapper",
993 "/xyz/openbmc_project/object_mapper",
994 "xyz.openbmc_project.ObjectMapper", "GetObject",
995 "/xyz/openbmc_project/VirtualMedia",
996 std::array<const char*, 0>());
997 });
998 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
Ed Tanoused398212021-06-09 17:05:54 -0700999 .privileges(redfish::privileges::getVirtualMediaCollection)
Ed Tanous22db1722021-06-09 10:53:51 -07001000 .methods(boost::beast::http::verb::get)(
1001 [](const crow::Request& /* req */,
1002 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1003 const std::string& name) {
1004 if (name != "bmc")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001005 {
Ed Tanous22db1722021-06-09 10:53:51 -07001006 messages::resourceNotFound(asyncResp->res, "VirtualMedia",
1007 name);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001008
1009 return;
1010 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001011
Ed Tanous22db1722021-06-09 10:53:51 -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 Tanous22db1722021-06-09 10:53:51 -07001018 crow::connections::systemBus->async_method_call(
1019 [asyncResp, name](const boost::system::error_code ec,
1020 const GetObjectType& getObjectType) {
1021 if (ec)
1022 {
1023 BMCWEB_LOG_ERROR
1024 << "ObjectMapper::GetObject call failed: "
1025 << ec;
1026 messages::internalError(asyncResp->res);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001027
Ed Tanous22db1722021-06-09 10:53:51 -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 Tanous22db1722021-06-09 10:53:51 -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",
1039 std::array<const char*, 0>());
1040 });
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001041
Ed Tanous22db1722021-06-09 10:53:51 -07001042 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001043 .privileges(redfish::privileges::getVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -07001044 .methods(boost::beast::http::verb::get)(
1045 [](const crow::Request& /* req */,
1046 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1047 const std::string& name, const std::string& resName) {
1048 if (name != "bmc")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001049 {
Ed Tanous22db1722021-06-09 10:53:51 -07001050 messages::resourceNotFound(asyncResp->res, "VirtualMedia",
1051 resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001052
1053 return;
1054 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001055
Ed Tanous22db1722021-06-09 10:53:51 -07001056 crow::connections::systemBus->async_method_call(
1057 [asyncResp, name,
1058 resName](const boost::system::error_code ec,
1059 const GetObjectType& getObjectType) {
1060 if (ec)
1061 {
1062 BMCWEB_LOG_ERROR
1063 << "ObjectMapper::GetObject call failed: "
1064 << ec;
1065 messages::internalError(asyncResp->res);
1066
1067 return;
1068 }
1069 std::string service = getObjectType.begin()->first;
1070 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1071
1072 getVmData(asyncResp, service, name, resName);
1073 },
1074 "xyz.openbmc_project.ObjectMapper",
1075 "/xyz/openbmc_project/object_mapper",
1076 "xyz.openbmc_project.ObjectMapper", "GetObject",
1077 "/xyz/openbmc_project/VirtualMedia",
1078 std::array<const char*, 0>());
1079 });
1080}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001081
1082} // namespace redfish