blob: 747ca43b047c702c55ac10cdb837ced915845f46 [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
zhanghch058d1b46d2021-04-01 11:18:24 +080060 vmParseInterfaceObject(const DbusInterfaceType& interface,
61 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020062{
63 const auto mountPointIface =
64 interface.find("xyz.openbmc_project.VirtualMedia.MountPoint");
65 if (mountPointIface == interface.cend())
66 {
67 BMCWEB_LOG_DEBUG << "Interface MountPoint not found";
68 return;
69 }
70
71 const auto processIface =
72 interface.find("xyz.openbmc_project.VirtualMedia.Process");
73 if (processIface == interface.cend())
74 {
75 BMCWEB_LOG_DEBUG << "Interface Process not found";
76 return;
77 }
78
79 const auto endpointIdProperty = mountPointIface->second.find("EndpointId");
80 if (endpointIdProperty == mountPointIface->second.cend())
81 {
82 BMCWEB_LOG_DEBUG << "Property EndpointId not found";
83 return;
84 }
85
86 const auto activeProperty = processIface->second.find("Active");
87 if (activeProperty == processIface->second.cend())
88 {
89 BMCWEB_LOG_DEBUG << "Property Active not found";
90 return;
91 }
92
Gunnar Mills1214b7e2020-06-04 10:11:30 -050093 const bool* activeValue = std::get_if<bool>(&activeProperty->second);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020094 if (!activeValue)
95 {
96 BMCWEB_LOG_DEBUG << "Value Active not found";
97 return;
98 }
99
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500100 const std::string* endpointIdValue =
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200101 std::get_if<std::string>(&endpointIdProperty->second);
102 if (endpointIdValue)
103 {
104 if (!endpointIdValue->empty())
105 {
106 // Proxy mode
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100107 aResp->res.jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
108 *endpointIdValue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200109 aResp->res.jsonValue["TransferProtocolType"] = "OEM";
110 aResp->res.jsonValue["Inserted"] = *activeValue;
111 if (*activeValue == true)
112 {
113 aResp->res.jsonValue["ConnectedVia"] = "Applet";
114 }
115 }
116 else
117 {
118 // Legacy mode
Anna Platash9e319cf2020-11-17 10:18:31 +0100119 for (const auto& property : mountPointIface->second)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200120 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100121 if (property.first == "ImageURL")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200122 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100123 const std::string* imageUrlValue =
124 std::get_if<std::string>(&property.second);
125 if (imageUrlValue && !imageUrlValue->empty())
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100126 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100127 std::filesystem::path filePath = *imageUrlValue;
128 if (!filePath.has_filename())
129 {
130 // this will handle https share, which not
131 // necessarily has to have filename given.
132 aResp->res.jsonValue["ImageName"] = "";
133 }
134 else
135 {
136 aResp->res.jsonValue["ImageName"] =
137 filePath.filename();
138 }
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100139
Anna Platash9e319cf2020-11-17 10:18:31 +0100140 aResp->res.jsonValue["Image"] = *imageUrlValue;
141 aResp->res.jsonValue["Inserted"] = *activeValue;
142 aResp->res.jsonValue["TransferProtocolType"] =
143 getTransferProtocolTypeFromUri(*imageUrlValue);
144
145 if (*activeValue == true)
146 {
147 aResp->res.jsonValue["ConnectedVia"] = "URI";
148 }
149 }
150 }
151 else if (property.first == "WriteProtected")
152 {
153 const bool* writeProtectedValue =
154 std::get_if<bool>(&property.second);
155 if (writeProtectedValue)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200156 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100157 aResp->res.jsonValue["WriteProtected"] =
158 *writeProtectedValue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200159 }
160 }
161 }
162 }
163 }
164}
165
166/**
167 * @brief Fill template for Virtual Media Item.
168 */
Ed Tanous22db1722021-06-09 10:53:51 -0700169inline nlohmann::json vmItemTemplate(const std::string& name,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500170 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200171{
172 nlohmann::json item;
Ed Tanous22db1722021-06-09 10:53:51 -0700173
174 std::string id = "/redfish/v1/Managers/";
175 id += name;
176 id += "/VirtualMedia/";
177 id += resName;
178 item["@odata.id"] = std::move(id);
179
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100180 item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200181 item["Name"] = "Virtual Removable Media";
182 item["Id"] = resName;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200183 item["WriteProtected"] = true;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200184 item["MediaTypes"] = {"CD", "USBStick"};
185 item["TransferMethod"] = "Stream";
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100186 item["Oem"]["OpenBMC"]["@odata.type"] =
187 "#OemVirtualMedia.v1_0_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200188
189 return item;
190}
191
192/**
193 * @brief Fills collection data
194 */
Ed Tanous22db1722021-06-09 10:53:51 -0700195inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500196 const std::string& service,
197 const std::string& name)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200198{
199 BMCWEB_LOG_DEBUG << "Get available Virtual Media resources.";
200 crow::connections::systemBus->async_method_call(
201 [name, aResp{std::move(aResp)}](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500202 ManagedObjectType& subtree) {
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200203 if (ec)
204 {
205 BMCWEB_LOG_DEBUG << "DBUS response error";
206 return;
207 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500208 nlohmann::json& members = aResp->res.jsonValue["Members"];
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200209 members = nlohmann::json::array();
210
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500211 for (const auto& object : subtree)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200212 {
213 nlohmann::json item;
Ed Tanous2dfd18e2020-12-18 00:41:31 +0000214 std::string path = object.first.filename();
215 if (path.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200216 {
217 continue;
218 }
219
Ed Tanous22db1722021-06-09 10:53:51 -0700220 std::string id = "/redfish/v1/Managers/";
221 id += name;
222 id += "/VirtualMedia/";
223 id += path;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200224
Ed Tanous22db1722021-06-09 10:53:51 -0700225 item["@odata.id"] = std::move(id);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200226 members.emplace_back(std::move(item));
227 }
228 aResp->res.jsonValue["Members@odata.count"] = members.size();
229 },
230 service, "/xyz/openbmc_project/VirtualMedia",
231 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
232}
233
234/**
235 * @brief Fills data for specific resource
236 */
Ed Tanous22db1722021-06-09 10:53:51 -0700237inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500238 const std::string& service, const std::string& name,
239 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200240{
241 BMCWEB_LOG_DEBUG << "Get Virtual Media resource data.";
242
243 crow::connections::systemBus->async_method_call(
244 [resName, name, aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500245 ManagedObjectType& subtree) {
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200246 if (ec)
247 {
248 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200249
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200250 return;
251 }
252
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500253 for (auto& item : subtree)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200254 {
Ed Tanous2dfd18e2020-12-18 00:41:31 +0000255 std::string thispath = item.first.filename();
256 if (thispath.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200257 {
258 continue;
259 }
260
Ed Tanous2dfd18e2020-12-18 00:41:31 +0000261 if (thispath != resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200262 {
263 continue;
264 }
265
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200266 // "Legacy"/"Proxy"
267 auto mode = item.first.parent_path();
268 // "VirtualMedia"
269 auto type = mode.parent_path();
270 if (mode.filename().empty() || type.filename().empty())
271 {
272 continue;
273 }
274
275 if (type.filename() != "VirtualMedia")
276 {
277 continue;
278 }
279
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200280 aResp->res.jsonValue = vmItemTemplate(name, resName);
Ed Tanous22db1722021-06-09 10:53:51 -0700281 std::string actionsId = "/redfish/v1/Managers/";
282 actionsId += name;
283 actionsId += "/VirtualMedia/";
284 actionsId += resName;
285 actionsId += "/Actions";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200286
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200287 // Check if dbus path is Legacy type
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200288 if (mode.filename() == "Legacy")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200289 {
290 aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
291 ["target"] =
Ed Tanous22db1722021-06-09 10:53:51 -0700292 actionsId + "/VirtualMedia.InsertMedia";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200293 }
294
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200295 vmParseInterfaceObject(item.second, aResp);
296
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200297 aResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"]
298 ["target"] =
Ed Tanous22db1722021-06-09 10:53:51 -0700299 actionsId + "/VirtualMedia.EjectMedia";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200300
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200301 return;
302 }
303
304 messages::resourceNotFound(
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100305 aResp->res, "#VirtualMedia.v1_3_0.VirtualMedia", resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200306 },
307 service, "/xyz/openbmc_project/VirtualMedia",
308 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
309}
310
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200311/**
Ed Tanous22db1722021-06-09 10:53:51 -0700312 * @brief Transfer protocols supported for InsertMedia action.
313 *
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200314 */
Ed Tanous22db1722021-06-09 10:53:51 -0700315enum class TransferProtocol
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200316{
Ed Tanous22db1722021-06-09 10:53:51 -0700317 https,
318 smb,
319 invalid
320};
321
322/**
323 * @brief Function extracts transfer protocol type from URI.
324 *
325 */
326inline std::optional<TransferProtocol>
327 getTransferProtocolFromUri(const std::string& imageUri)
328{
Ed Tanousd32c4fa2021-09-14 13:16:51 -0700329 boost::urls::error_code ec;
330 boost::urls::url_view url =
331 boost::urls::parse_uri(boost::string_view(imageUri), ec);
332 if (ec)
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200333 {
Ed Tanousd32c4fa2021-09-14 13:16:51 -0700334 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100335 }
Ed Tanousd32c4fa2021-09-14 13:16:51 -0700336
337 boost::string_view scheme = url.scheme();
338 if (scheme == "smb")
Agata Olenderc6f4e012020-03-11 15:19:07 +0100339 {
Ed Tanousd32c4fa2021-09-14 13:16:51 -0700340 return TransferProtocol::smb;
341 }
342 if (scheme == "https")
343 {
344 return TransferProtocol::https;
345 }
346 if (!scheme.empty())
347 {
348 return TransferProtocol::invalid;
Agata Olenderc6f4e012020-03-11 15:19:07 +0100349 }
350
Ed Tanous22db1722021-06-09 10:53:51 -0700351 return {};
352}
353
354/**
355 * @brief Function convert transfer protocol from string param.
356 *
357 */
358inline std::optional<TransferProtocol> getTransferProtocolFromParam(
359 const std::optional<std::string>& transferProtocolType)
360{
361 if (transferProtocolType == std::nullopt)
Agata Olenderc6f4e012020-03-11 15:19:07 +0100362 {
Ed Tanous22db1722021-06-09 10:53:51 -0700363 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100364 }
365
Ed Tanous22db1722021-06-09 10:53:51 -0700366 if (*transferProtocolType == "CIFS")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200367 {
Ed Tanous22db1722021-06-09 10:53:51 -0700368 return TransferProtocol::smb;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200369 }
370
Ed Tanous22db1722021-06-09 10:53:51 -0700371 if (*transferProtocolType == "HTTPS")
372 {
373 return TransferProtocol::https;
374 }
375
376 return TransferProtocol::invalid;
377}
378
379/**
380 * @brief Function extends URI with transfer protocol type.
381 *
382 */
383inline std::string
384 getUriWithTransferProtocol(const std::string& imageUri,
385 const TransferProtocol& transferProtocol)
386{
387 if (transferProtocol == TransferProtocol::smb)
388 {
389 return "smb://" + imageUri;
390 }
391
392 if (transferProtocol == TransferProtocol::https)
393 {
394 return "https://" + imageUri;
395 }
396
397 return imageUri;
398}
399
400/**
401 * @brief Function validate parameters of insert media request.
402 *
403 */
404inline bool
405 validateParams(crow::Response& res, std::string& imageUrl,
406 const std::optional<bool>& inserted,
407 const std::optional<std::string>& transferMethod,
408 const std::optional<std::string>& transferProtocolType)
409{
410 BMCWEB_LOG_DEBUG << "Validation started";
411 // required param imageUrl must not be empty
412 if (imageUrl.empty())
413 {
414 BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
415
416 messages::propertyValueFormatError(res, "<empty>", "Image");
417
418 return false;
419 }
420
421 // optional param inserted must be true
422 if ((inserted != std::nullopt) && (*inserted != true))
423 {
424 BMCWEB_LOG_ERROR
425 << "Request action optional parameter Inserted must be true.";
426
427 messages::actionParameterNotSupported(res, "Inserted", "InsertMedia");
428
429 return false;
430 }
431
432 // optional param transferMethod must be stream
433 if ((transferMethod != std::nullopt) && (*transferMethod != "Stream"))
434 {
435 BMCWEB_LOG_ERROR << "Request action optional parameter "
436 "TransferMethod must be Stream.";
437
438 messages::actionParameterNotSupported(res, "TransferMethod",
439 "InsertMedia");
440
441 return false;
442 }
443
444 std::optional<TransferProtocol> uriTransferProtocolType =
445 getTransferProtocolFromUri(imageUrl);
446
447 std::optional<TransferProtocol> paramTransferProtocolType =
448 getTransferProtocolFromParam(transferProtocolType);
449
450 // ImageUrl does not contain valid protocol type
451 if (*uriTransferProtocolType == TransferProtocol::invalid)
452 {
453 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
454 "contain specified protocol type from list: "
455 "(smb, https).";
456
457 messages::resourceAtUriInUnknownFormat(res, imageUrl);
458
459 return false;
460 }
461
462 // transferProtocolType should contain value from list
463 if (*paramTransferProtocolType == TransferProtocol::invalid)
464 {
465 BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
466 "must be provided with value from list: "
467 "(CIFS, HTTPS).";
468
469 messages::propertyValueNotInList(res, *transferProtocolType,
470 "TransferProtocolType");
471 return false;
472 }
473
474 // valid transfer protocol not provided either with URI nor param
475 if ((uriTransferProtocolType == std::nullopt) &&
476 (paramTransferProtocolType == std::nullopt))
477 {
478 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
479 "contain specified protocol type or param "
480 "TransferProtocolType must be provided.";
481
482 messages::resourceAtUriInUnknownFormat(res, imageUrl);
483
484 return false;
485 }
486
487 // valid transfer protocol provided both with URI and param
488 if ((paramTransferProtocolType != std::nullopt) &&
489 (uriTransferProtocolType != std::nullopt))
490 {
491 // check if protocol is the same for URI and param
492 if (*paramTransferProtocolType != *uriTransferProtocolType)
493 {
494 BMCWEB_LOG_ERROR << "Request action parameter "
495 "TransferProtocolType must contain the "
496 "same protocol type as protocol type "
497 "provided with param imageUrl.";
498
499 messages::actionParameterValueTypeError(res, *transferProtocolType,
500 "TransferProtocolType",
501 "InsertMedia");
502
503 return false;
504 }
505 }
506
507 // validation passed
508 // add protocol to URI if needed
509 if (uriTransferProtocolType == std::nullopt)
510 {
511 imageUrl =
512 getUriWithTransferProtocol(imageUrl, *paramTransferProtocolType);
513 }
514
515 return true;
516}
517
518template <typename T>
519static void secureCleanup(T& value)
520{
521 auto raw = const_cast<typename T::value_type*>(value.data());
522 explicit_bzero(raw, value.size() * sizeof(*raw));
523}
524
525class Credentials
526{
527 public:
528 Credentials(std::string&& user, std::string&& password) :
529 userBuf(std::move(user)), passBuf(std::move(password))
530 {}
531
532 ~Credentials()
533 {
534 secureCleanup(userBuf);
535 secureCleanup(passBuf);
536 }
537
538 const std::string& user()
539 {
540 return userBuf;
541 }
542
543 const std::string& password()
544 {
545 return passBuf;
546 }
547
548 Credentials() = delete;
549 Credentials(const Credentials&) = delete;
550 Credentials& operator=(const Credentials&) = delete;
551
552 private:
553 std::string userBuf;
554 std::string passBuf;
555};
556
557class CredentialsProvider
558{
559 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500560 template <typename T>
Ed Tanous22db1722021-06-09 10:53:51 -0700561 struct Deleter
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100562 {
Ed Tanous22db1722021-06-09 10:53:51 -0700563 void operator()(T* buff) const
564 {
565 if (buff)
566 {
567 secureCleanup(*buff);
568 delete buff;
569 }
570 }
571 };
572
573 using Buffer = std::vector<char>;
574 using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
575 // Using explicit definition instead of std::function to avoid implicit
576 // conversions eg. stack copy instead of reference
577 using FormatterFunc = void(const std::string& username,
578 const std::string& password, Buffer& dest);
579
580 CredentialsProvider(std::string&& user, std::string&& password) :
581 credentials(std::move(user), std::move(password))
582 {}
583
584 const std::string& user()
585 {
586 return credentials.user();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100587 }
588
Ed Tanous22db1722021-06-09 10:53:51 -0700589 const std::string& password()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100590 {
Ed Tanous22db1722021-06-09 10:53:51 -0700591 return credentials.password();
592 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100593
Ed Tanous22db1722021-06-09 10:53:51 -0700594 SecureBuffer pack(FormatterFunc formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100595 {
Ed Tanous22db1722021-06-09 10:53:51 -0700596 SecureBuffer packed{new Buffer{}};
597 if (formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100598 {
Ed Tanous22db1722021-06-09 10:53:51 -0700599 formatter(credentials.user(), credentials.password(), *packed);
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100600 }
601
Ed Tanous22db1722021-06-09 10:53:51 -0700602 return packed;
603 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100604
Ed Tanous22db1722021-06-09 10:53:51 -0700605 private:
606 Credentials credentials;
607};
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100608
Ed Tanous22db1722021-06-09 10:53:51 -0700609// Wrapper for boost::async_pipe ensuring proper pipe cleanup
610template <typename Buffer>
611class Pipe
612{
613 public:
614 using unix_fd = sdbusplus::message::unix_fd;
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100615
Ed Tanous22db1722021-06-09 10:53:51 -0700616 Pipe(boost::asio::io_context& io, Buffer&& buffer) :
617 impl(io), buffer{std::move(buffer)}
618 {}
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100619
Ed Tanous22db1722021-06-09 10:53:51 -0700620 ~Pipe()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100621 {
Ed Tanous22db1722021-06-09 10:53:51 -0700622 // Named pipe needs to be explicitly removed
623 impl.close();
624 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100625
Ed Tanous22db1722021-06-09 10:53:51 -0700626 unix_fd fd()
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200627 {
Ed Tanous22db1722021-06-09 10:53:51 -0700628 return unix_fd{impl.native_source()};
629 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100630
Ed Tanous22db1722021-06-09 10:53:51 -0700631 template <typename WriteHandler>
632 void asyncWrite(WriteHandler&& handler)
633 {
634 impl.async_write_some(data(), std::forward<WriteHandler>(handler));
635 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100636
Ed Tanous22db1722021-06-09 10:53:51 -0700637 private:
638 // Specialization for pointer types
639 template <typename B = Buffer>
640 typename std::enable_if<boost::has_dereference<B>::value,
641 boost::asio::const_buffer>::type
642 data()
643 {
644 return boost::asio::buffer(*buffer);
645 }
646
647 template <typename B = Buffer>
648 typename std::enable_if<!boost::has_dereference<B>::value,
649 boost::asio::const_buffer>::type
650 data()
651 {
652 return boost::asio::buffer(buffer);
653 }
654
655 const std::string name;
656 boost::process::async_pipe impl;
657 Buffer buffer;
658};
659
660/**
661 * @brief Function transceives data with dbus directly.
662 *
663 * All BMC state properties will be retrieved before sending reset request.
664 */
665inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
666 const std::string& service, const std::string& name,
667 const std::string& imageUrl, const bool rw,
668 std::string&& userName, std::string&& password)
669{
670 using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
671 constexpr const size_t secretLimit = 1024;
672
673 std::shared_ptr<SecurePipe> secretPipe;
Ed Tanous168e20c2021-12-13 14:39:53 -0800674 dbus::utility::DbusVariantType unixFd = -1;
Ed Tanous22db1722021-06-09 10:53:51 -0700675
676 if (!userName.empty() || !password.empty())
677 {
678 // Encapsulate in safe buffer
679 CredentialsProvider credentials(std::move(userName),
680 std::move(password));
681
682 // Payload must contain data + NULL delimiters
683 if (credentials.user().size() + credentials.password().size() + 2 >
684 secretLimit)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100685 {
Ed Tanous22db1722021-06-09 10:53:51 -0700686 BMCWEB_LOG_ERROR << "Credentials too long to handle";
687 messages::unrecognizedRequestBody(asyncResp->res);
688 return;
689 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100690
Ed Tanous22db1722021-06-09 10:53:51 -0700691 // Pack secret
692 auto secret = credentials.pack(
693 [](const auto& user, const auto& pass, auto& buff) {
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100694 std::copy(user.begin(), user.end(), std::back_inserter(buff));
695 buff.push_back('\0');
696 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
697 buff.push_back('\0');
698 });
699
Ed Tanous22db1722021-06-09 10:53:51 -0700700 // Open pipe
701 secretPipe = std::make_shared<SecurePipe>(
702 crow::connections::systemBus->get_io_context(), std::move(secret));
703 unixFd = secretPipe->fd();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100704
Ed Tanous22db1722021-06-09 10:53:51 -0700705 // Pass secret over pipe
706 secretPipe->asyncWrite(
707 [asyncResp](const boost::system::error_code& ec, std::size_t) {
708 if (ec)
709 {
710 BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
711 messages::internalError(asyncResp->res);
712 }
713 });
714 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100715
Ed Tanous22db1722021-06-09 10:53:51 -0700716 crow::connections::systemBus->async_method_call(
717 [asyncResp, secretPipe](const boost::system::error_code ec,
718 bool success) {
719 if (ec)
720 {
721 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
722 messages::internalError(asyncResp->res);
723 }
724 else if (!success)
725 {
726 BMCWEB_LOG_ERROR << "Service responded with error";
727 messages::generalError(asyncResp->res);
728 }
729 },
730 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
731 "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
732 unixFd);
733}
734
735/**
736 * @brief Function transceives data with dbus directly.
737 *
738 * All BMC state properties will be retrieved before sending reset request.
739 */
740inline void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
741 const std::string& service, const std::string& name,
742 bool legacy)
743{
744
745 // Legacy mount requires parameter with image
746 if (legacy)
747 {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100748 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700749 [asyncResp](const boost::system::error_code ec) {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100750 if (ec)
751 {
752 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700753
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100754 messages::internalError(asyncResp->res);
Ed Tanous22db1722021-06-09 10:53:51 -0700755 return;
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100756 }
757 },
758 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
Ed Tanous22db1722021-06-09 10:53:51 -0700759 "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200760 }
Ed Tanous22db1722021-06-09 10:53:51 -0700761 else // proxy
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200762 {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200763 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700764 [asyncResp](const boost::system::error_code ec) {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200765 if (ec)
766 {
Ed Tanous22db1722021-06-09 10:53:51 -0700767 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
768
zhanghch058d1b46d2021-04-01 11:18:24 +0800769 messages::internalError(asyncResp->res);
Ed Tanous22db1722021-06-09 10:53:51 -0700770 return;
771 }
772 },
773 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
774 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
775 }
776}
777
Ed Tanous98be3e32021-09-16 15:05:36 -0700778struct InsertMediaActionParams
779{
780 std::string imageUrl;
781 std::optional<std::string> userName;
782 std::optional<std::string> password;
783 std::optional<std::string> transferMethod;
784 std::optional<std::string> transferProtocolType;
785 std::optional<bool> writeProtected = true;
786 std::optional<bool> inserted;
787};
788
Ed Tanous22db1722021-06-09 10:53:51 -0700789inline void requestNBDVirtualMediaRoutes(App& app)
790{
George Liu0fda0f12021-11-16 10:06:17 +0800791 BMCWEB_ROUTE(
792 app,
793 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
Ed Tanoused398212021-06-09 17:05:54 -0700794 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -0700795 .methods(boost::beast::http::verb::post)(
796 [](const crow::Request& req,
797 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
798 const std::string& name, const std::string& resName) {
799 if (name != "bmc")
800 {
801 messages::resourceNotFound(asyncResp->res,
802 "VirtualMedia.Insert", resName);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200803
804 return;
805 }
Ed Tanous98be3e32021-09-16 15:05:36 -0700806 InsertMediaActionParams actionParams;
807
808 // Read obligatory parameters (url of
809 // image)
810 if (!json_util::readJson(
811 req, asyncResp->res, "Image", actionParams.imageUrl,
812 "WriteProtected", actionParams.writeProtected,
813 "UserName", actionParams.userName, "Password",
814 actionParams.password, "Inserted",
815 actionParams.inserted, "TransferMethod",
816 actionParams.transferMethod, "TransferProtocolType",
817 actionParams.transferProtocolType))
818 {
819 BMCWEB_LOG_DEBUG << "Image is not provided";
820 return;
821 }
822
823 bool paramsValid = validateParams(
824 asyncResp->res, actionParams.imageUrl,
825 actionParams.inserted, actionParams.transferMethod,
826 actionParams.transferProtocolType);
827
828 if (paramsValid == false)
829 {
830 return;
831 }
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200832
833 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700834 [asyncResp, actionParams,
Ed Tanous22db1722021-06-09 10:53:51 -0700835 resName](const boost::system::error_code ec,
Ed Tanous98be3e32021-09-16 15:05:36 -0700836 const GetObjectType& getObjectType) mutable {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200837 if (ec)
838 {
Ed Tanous22db1722021-06-09 10:53:51 -0700839 BMCWEB_LOG_ERROR
840 << "ObjectMapper::GetObject call failed: "
841 << ec;
842 messages::internalError(asyncResp->res);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200843
844 return;
845 }
Ed Tanous22db1722021-06-09 10:53:51 -0700846 std::string service = getObjectType.begin()->first;
847 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200848
Ed Tanous22db1722021-06-09 10:53:51 -0700849 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700850 [service, resName, actionParams,
Ed Tanous22db1722021-06-09 10:53:51 -0700851 asyncResp](const boost::system::error_code ec,
Ed Tanous98be3e32021-09-16 15:05:36 -0700852 ManagedObjectType& subtree) mutable {
Ed Tanous22db1722021-06-09 10:53:51 -0700853 if (ec)
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200854 {
Ed Tanous22db1722021-06-09 10:53:51 -0700855 BMCWEB_LOG_DEBUG << "DBUS response error";
856
857 return;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200858 }
859
Ed Tanous22db1722021-06-09 10:53:51 -0700860 for (const auto& object : subtree)
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200861 {
Ed Tanous22db1722021-06-09 10:53:51 -0700862 const std::string& path =
863 static_cast<const std::string&>(
864 object.first);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200865
Ed Tanous22db1722021-06-09 10:53:51 -0700866 std::size_t lastIndex = path.rfind('/');
867 if (lastIndex == std::string::npos)
868 {
869 continue;
870 }
871
872 lastIndex += 1;
873
874 if (path.substr(lastIndex) == resName)
875 {
876 lastIndex = path.rfind("Proxy");
877 if (lastIndex != std::string::npos)
878 {
879 // Not possible in proxy mode
880 BMCWEB_LOG_DEBUG
881 << "InsertMedia not "
882 "allowed in proxy mode";
883 messages::resourceNotFound(
884 asyncResp->res,
885 "VirtualMedia.InsertMedia",
886 resName);
887
888 return;
889 }
890
891 lastIndex = path.rfind("Legacy");
892 if (lastIndex == std::string::npos)
893 {
894 continue;
895 }
896
Ed Tanous22db1722021-06-09 10:53:51 -0700897 // manager is irrelevant for
898 // VirtualMedia dbus calls
Ed Tanous98be3e32021-09-16 15:05:36 -0700899 doMountVmLegacy(
900 asyncResp, service, resName,
901 actionParams.imageUrl,
902 !(*actionParams.writeProtected),
903 std::move(*actionParams.userName),
904 std::move(*actionParams.password));
Ed Tanous22db1722021-06-09 10:53:51 -0700905
906 return;
907 }
908 }
909 BMCWEB_LOG_DEBUG << "Parent item not found";
910 messages::resourceNotFound(
911 asyncResp->res, "VirtualMedia", resName);
912 },
913 service, "/xyz/openbmc_project/VirtualMedia",
914 "org.freedesktop.DBus.ObjectManager",
915 "GetManagedObjects");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200916 },
Ed Tanous22db1722021-06-09 10:53:51 -0700917 "xyz.openbmc_project.ObjectMapper",
918 "/xyz/openbmc_project/object_mapper",
919 "xyz.openbmc_project.ObjectMapper", "GetObject",
920 "/xyz/openbmc_project/VirtualMedia",
921 std::array<const char*, 0>());
922 });
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200923
George Liu0fda0f12021-11-16 10:06:17 +0800924 BMCWEB_ROUTE(
925 app,
926 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
Ed Tanoused398212021-06-09 17:05:54 -0700927 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -0700928 .methods(boost::beast::http::verb::post)(
Ed Tanous98be3e32021-09-16 15:05:36 -0700929 [](const crow::Request&,
Ed Tanous22db1722021-06-09 10:53:51 -0700930 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
931 const std::string& name, const std::string& resName) {
932 if (name != "bmc")
933 {
934 messages::resourceNotFound(asyncResp->res,
935 "VirtualMedia.Eject", resName);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200936
Ed Tanous22db1722021-06-09 10:53:51 -0700937 return;
938 }
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200939
Ed Tanous22db1722021-06-09 10:53:51 -0700940 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700941 [asyncResp, resName](const boost::system::error_code ec,
942 const GetObjectType& getObjectType) {
Ed Tanous22db1722021-06-09 10:53:51 -0700943 if (ec)
944 {
945 BMCWEB_LOG_ERROR
946 << "ObjectMapper::GetObject call failed: "
947 << ec;
948 messages::internalError(asyncResp->res);
949
950 return;
951 }
952 std::string service = getObjectType.begin()->first;
953 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
954
955 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700956 [resName, service, asyncResp{asyncResp}](
Ed Tanous22db1722021-06-09 10:53:51 -0700957 const boost::system::error_code ec,
958 ManagedObjectType& subtree) {
959 if (ec)
960 {
961 BMCWEB_LOG_DEBUG << "DBUS response error";
962
963 return;
964 }
965
966 for (const auto& object : subtree)
967 {
968 const std::string& path =
969 static_cast<const std::string&>(
970 object.first);
971
972 std::size_t lastIndex = path.rfind('/');
973 if (lastIndex == std::string::npos)
974 {
975 continue;
976 }
977
978 lastIndex += 1;
979
980 if (path.substr(lastIndex) == resName)
981 {
982 lastIndex = path.rfind("Proxy");
983 if (lastIndex != std::string::npos)
984 {
985 // Proxy mode
986 doVmAction(asyncResp, service,
987 resName, false);
988 }
989
990 lastIndex = path.rfind("Legacy");
991 if (lastIndex != std::string::npos)
992 {
993 // Legacy mode
994 doVmAction(asyncResp, service,
995 resName, true);
996 }
997
998 return;
999 }
1000 }
1001 BMCWEB_LOG_DEBUG << "Parent item not found";
1002 messages::resourceNotFound(
1003 asyncResp->res, "VirtualMedia", resName);
1004 },
1005 service, "/xyz/openbmc_project/VirtualMedia",
1006 "org.freedesktop.DBus.ObjectManager",
1007 "GetManagedObjects");
1008 },
1009 "xyz.openbmc_project.ObjectMapper",
1010 "/xyz/openbmc_project/object_mapper",
1011 "xyz.openbmc_project.ObjectMapper", "GetObject",
1012 "/xyz/openbmc_project/VirtualMedia",
1013 std::array<const char*, 0>());
1014 });
1015 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
Ed Tanoused398212021-06-09 17:05:54 -07001016 .privileges(redfish::privileges::getVirtualMediaCollection)
Ed Tanous22db1722021-06-09 10:53:51 -07001017 .methods(boost::beast::http::verb::get)(
1018 [](const crow::Request& /* req */,
1019 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1020 const std::string& name) {
1021 if (name != "bmc")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001022 {
Ed Tanous22db1722021-06-09 10:53:51 -07001023 messages::resourceNotFound(asyncResp->res, "VirtualMedia",
1024 name);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001025
1026 return;
1027 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001028
Ed Tanous22db1722021-06-09 10:53:51 -07001029 asyncResp->res.jsonValue["@odata.type"] =
1030 "#VirtualMediaCollection.VirtualMediaCollection";
1031 asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
1032 asyncResp->res.jsonValue["@odata.id"] =
1033 "/redfish/v1/Managers/" + name + "/VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001034
Ed Tanous22db1722021-06-09 10:53:51 -07001035 crow::connections::systemBus->async_method_call(
1036 [asyncResp, name](const boost::system::error_code ec,
1037 const GetObjectType& getObjectType) {
1038 if (ec)
1039 {
1040 BMCWEB_LOG_ERROR
1041 << "ObjectMapper::GetObject call failed: "
1042 << ec;
1043 messages::internalError(asyncResp->res);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001044
Ed Tanous22db1722021-06-09 10:53:51 -07001045 return;
1046 }
1047 std::string service = getObjectType.begin()->first;
1048 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001049
Ed Tanous22db1722021-06-09 10:53:51 -07001050 getVmResourceList(asyncResp, service, name);
1051 },
1052 "xyz.openbmc_project.ObjectMapper",
1053 "/xyz/openbmc_project/object_mapper",
1054 "xyz.openbmc_project.ObjectMapper", "GetObject",
1055 "/xyz/openbmc_project/VirtualMedia",
1056 std::array<const char*, 0>());
1057 });
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001058
Ed Tanous22db1722021-06-09 10:53:51 -07001059 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001060 .privileges(redfish::privileges::getVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -07001061 .methods(boost::beast::http::verb::get)(
1062 [](const crow::Request& /* req */,
1063 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1064 const std::string& name, const std::string& resName) {
1065 if (name != "bmc")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001066 {
Ed Tanous22db1722021-06-09 10:53:51 -07001067 messages::resourceNotFound(asyncResp->res, "VirtualMedia",
1068 resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001069
1070 return;
1071 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001072
Ed Tanous22db1722021-06-09 10:53:51 -07001073 crow::connections::systemBus->async_method_call(
1074 [asyncResp, name,
1075 resName](const boost::system::error_code ec,
1076 const GetObjectType& getObjectType) {
1077 if (ec)
1078 {
1079 BMCWEB_LOG_ERROR
1080 << "ObjectMapper::GetObject call failed: "
1081 << ec;
1082 messages::internalError(asyncResp->res);
1083
1084 return;
1085 }
1086 std::string service = getObjectType.begin()->first;
1087 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1088
1089 getVmData(asyncResp, service, name, resName);
1090 },
1091 "xyz.openbmc_project.ObjectMapper",
1092 "/xyz/openbmc_project/object_mapper",
1093 "xyz.openbmc_project.ObjectMapper", "GetObject",
1094 "/xyz/openbmc_project/VirtualMedia",
1095 std::array<const char*, 0>());
1096 });
1097}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001098
1099} // namespace redfish