blob: 9333f6168f03ac1a109848eb5a1a60cd1cee0aa9 [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);
Ed Tanous26f69762022-01-25 09:49:11 -080090 if (imageUrlValue != nullptr && !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(
Ed Tanous914e2d52022-01-07 11:38:34 -0800226 [resName, name,
227 aResp](const boost::system::error_code ec,
228 const dbus::utility::ManagedObjectType& subtree) {
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200229 if (ec)
230 {
231 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200232
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200233 return;
234 }
235
Ed Tanous914e2d52022-01-07 11:38:34 -0800236 for (const auto& item : subtree)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200237 {
Ed Tanous2dfd18e2020-12-18 00:41:31 +0000238 std::string thispath = item.first.filename();
239 if (thispath.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200240 {
241 continue;
242 }
243
Ed Tanous2dfd18e2020-12-18 00:41:31 +0000244 if (thispath != resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200245 {
246 continue;
247 }
248
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200249 // "Legacy"/"Proxy"
250 auto mode = item.first.parent_path();
251 // "VirtualMedia"
252 auto type = mode.parent_path();
253 if (mode.filename().empty() || type.filename().empty())
254 {
255 continue;
256 }
257
258 if (type.filename() != "VirtualMedia")
259 {
260 continue;
261 }
262
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200263 aResp->res.jsonValue = vmItemTemplate(name, resName);
Ed Tanous22db1722021-06-09 10:53:51 -0700264 std::string actionsId = "/redfish/v1/Managers/";
265 actionsId += name;
266 actionsId += "/VirtualMedia/";
267 actionsId += resName;
268 actionsId += "/Actions";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200269
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200270 // Check if dbus path is Legacy type
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200271 if (mode.filename() == "Legacy")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200272 {
273 aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
274 ["target"] =
Ed Tanous22db1722021-06-09 10:53:51 -0700275 actionsId + "/VirtualMedia.InsertMedia";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200276 }
277
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200278 vmParseInterfaceObject(item.second, aResp);
279
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200280 aResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"]
281 ["target"] =
Ed Tanous22db1722021-06-09 10:53:51 -0700282 actionsId + "/VirtualMedia.EjectMedia";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200283
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200284 return;
285 }
286
287 messages::resourceNotFound(
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100288 aResp->res, "#VirtualMedia.v1_3_0.VirtualMedia", resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200289 },
290 service, "/xyz/openbmc_project/VirtualMedia",
291 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
292}
293
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200294/**
Ed Tanous22db1722021-06-09 10:53:51 -0700295 * @brief Transfer protocols supported for InsertMedia action.
296 *
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200297 */
Ed Tanous22db1722021-06-09 10:53:51 -0700298enum class TransferProtocol
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200299{
Ed Tanous22db1722021-06-09 10:53:51 -0700300 https,
301 smb,
302 invalid
303};
304
305/**
306 * @brief Function extracts transfer protocol type from URI.
307 *
308 */
309inline std::optional<TransferProtocol>
310 getTransferProtocolFromUri(const std::string& imageUri)
311{
Ed Tanousd32c4fa2021-09-14 13:16:51 -0700312 boost::urls::error_code ec;
313 boost::urls::url_view url =
314 boost::urls::parse_uri(boost::string_view(imageUri), ec);
315 if (ec)
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200316 {
Ed Tanousd32c4fa2021-09-14 13:16:51 -0700317 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100318 }
Ed Tanousd32c4fa2021-09-14 13:16:51 -0700319
320 boost::string_view scheme = url.scheme();
321 if (scheme == "smb")
Agata Olenderc6f4e012020-03-11 15:19:07 +0100322 {
Ed Tanousd32c4fa2021-09-14 13:16:51 -0700323 return TransferProtocol::smb;
324 }
325 if (scheme == "https")
326 {
327 return TransferProtocol::https;
328 }
329 if (!scheme.empty())
330 {
331 return TransferProtocol::invalid;
Agata Olenderc6f4e012020-03-11 15:19:07 +0100332 }
333
Ed Tanous22db1722021-06-09 10:53:51 -0700334 return {};
335}
336
337/**
338 * @brief Function convert transfer protocol from string param.
339 *
340 */
341inline std::optional<TransferProtocol> getTransferProtocolFromParam(
342 const std::optional<std::string>& transferProtocolType)
343{
344 if (transferProtocolType == std::nullopt)
Agata Olenderc6f4e012020-03-11 15:19:07 +0100345 {
Ed Tanous22db1722021-06-09 10:53:51 -0700346 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100347 }
348
Ed Tanous22db1722021-06-09 10:53:51 -0700349 if (*transferProtocolType == "CIFS")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200350 {
Ed Tanous22db1722021-06-09 10:53:51 -0700351 return TransferProtocol::smb;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200352 }
353
Ed Tanous22db1722021-06-09 10:53:51 -0700354 if (*transferProtocolType == "HTTPS")
355 {
356 return TransferProtocol::https;
357 }
358
359 return TransferProtocol::invalid;
360}
361
362/**
363 * @brief Function extends URI with transfer protocol type.
364 *
365 */
366inline std::string
367 getUriWithTransferProtocol(const std::string& imageUri,
368 const TransferProtocol& transferProtocol)
369{
370 if (transferProtocol == TransferProtocol::smb)
371 {
372 return "smb://" + imageUri;
373 }
374
375 if (transferProtocol == TransferProtocol::https)
376 {
377 return "https://" + imageUri;
378 }
379
380 return imageUri;
381}
382
383/**
384 * @brief Function validate parameters of insert media request.
385 *
386 */
387inline bool
388 validateParams(crow::Response& res, std::string& imageUrl,
389 const std::optional<bool>& inserted,
390 const std::optional<std::string>& transferMethod,
391 const std::optional<std::string>& transferProtocolType)
392{
393 BMCWEB_LOG_DEBUG << "Validation started";
394 // required param imageUrl must not be empty
395 if (imageUrl.empty())
396 {
397 BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
398
399 messages::propertyValueFormatError(res, "<empty>", "Image");
400
401 return false;
402 }
403
404 // optional param inserted must be true
405 if ((inserted != std::nullopt) && (*inserted != true))
406 {
407 BMCWEB_LOG_ERROR
408 << "Request action optional parameter Inserted must be true.";
409
410 messages::actionParameterNotSupported(res, "Inserted", "InsertMedia");
411
412 return false;
413 }
414
415 // optional param transferMethod must be stream
416 if ((transferMethod != std::nullopt) && (*transferMethod != "Stream"))
417 {
418 BMCWEB_LOG_ERROR << "Request action optional parameter "
419 "TransferMethod must be Stream.";
420
421 messages::actionParameterNotSupported(res, "TransferMethod",
422 "InsertMedia");
423
424 return false;
425 }
426
427 std::optional<TransferProtocol> uriTransferProtocolType =
428 getTransferProtocolFromUri(imageUrl);
429
430 std::optional<TransferProtocol> paramTransferProtocolType =
431 getTransferProtocolFromParam(transferProtocolType);
432
433 // ImageUrl does not contain valid protocol type
434 if (*uriTransferProtocolType == TransferProtocol::invalid)
435 {
436 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
437 "contain specified protocol type from list: "
438 "(smb, https).";
439
440 messages::resourceAtUriInUnknownFormat(res, imageUrl);
441
442 return false;
443 }
444
445 // transferProtocolType should contain value from list
446 if (*paramTransferProtocolType == TransferProtocol::invalid)
447 {
448 BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
449 "must be provided with value from list: "
450 "(CIFS, HTTPS).";
451
452 messages::propertyValueNotInList(res, *transferProtocolType,
453 "TransferProtocolType");
454 return false;
455 }
456
457 // valid transfer protocol not provided either with URI nor param
458 if ((uriTransferProtocolType == std::nullopt) &&
459 (paramTransferProtocolType == std::nullopt))
460 {
461 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
462 "contain specified protocol type or param "
463 "TransferProtocolType must be provided.";
464
465 messages::resourceAtUriInUnknownFormat(res, imageUrl);
466
467 return false;
468 }
469
470 // valid transfer protocol provided both with URI and param
471 if ((paramTransferProtocolType != std::nullopt) &&
472 (uriTransferProtocolType != std::nullopt))
473 {
474 // check if protocol is the same for URI and param
475 if (*paramTransferProtocolType != *uriTransferProtocolType)
476 {
477 BMCWEB_LOG_ERROR << "Request action parameter "
478 "TransferProtocolType must contain the "
479 "same protocol type as protocol type "
480 "provided with param imageUrl.";
481
482 messages::actionParameterValueTypeError(res, *transferProtocolType,
483 "TransferProtocolType",
484 "InsertMedia");
485
486 return false;
487 }
488 }
489
490 // validation passed
491 // add protocol to URI if needed
492 if (uriTransferProtocolType == std::nullopt)
493 {
494 imageUrl =
495 getUriWithTransferProtocol(imageUrl, *paramTransferProtocolType);
496 }
497
498 return true;
499}
500
501template <typename T>
502static void secureCleanup(T& value)
503{
Ed Tanous4ecc6182022-01-07 09:36:26 -0800504 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
Ed Tanous22db1722021-06-09 10:53:51 -0700505 auto raw = const_cast<typename T::value_type*>(value.data());
506 explicit_bzero(raw, value.size() * sizeof(*raw));
507}
508
509class Credentials
510{
511 public:
512 Credentials(std::string&& user, std::string&& password) :
513 userBuf(std::move(user)), passBuf(std::move(password))
514 {}
515
516 ~Credentials()
517 {
518 secureCleanup(userBuf);
519 secureCleanup(passBuf);
520 }
521
522 const std::string& user()
523 {
524 return userBuf;
525 }
526
527 const std::string& password()
528 {
529 return passBuf;
530 }
531
532 Credentials() = delete;
533 Credentials(const Credentials&) = delete;
534 Credentials& operator=(const Credentials&) = delete;
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800535 Credentials(Credentials&&) = delete;
536 Credentials& operator=(Credentials&&) = delete;
Ed Tanous22db1722021-06-09 10:53:51 -0700537
538 private:
539 std::string userBuf;
540 std::string passBuf;
541};
542
543class CredentialsProvider
544{
545 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500546 template <typename T>
Ed Tanous22db1722021-06-09 10:53:51 -0700547 struct Deleter
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100548 {
Ed Tanous22db1722021-06-09 10:53:51 -0700549 void operator()(T* buff) const
550 {
551 if (buff)
552 {
553 secureCleanup(*buff);
554 delete buff;
555 }
556 }
557 };
558
559 using Buffer = std::vector<char>;
560 using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
561 // Using explicit definition instead of std::function to avoid implicit
562 // conversions eg. stack copy instead of reference
563 using FormatterFunc = void(const std::string& username,
564 const std::string& password, Buffer& dest);
565
566 CredentialsProvider(std::string&& user, std::string&& password) :
567 credentials(std::move(user), std::move(password))
568 {}
569
570 const std::string& user()
571 {
572 return credentials.user();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100573 }
574
Ed Tanous22db1722021-06-09 10:53:51 -0700575 const std::string& password()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100576 {
Ed Tanous22db1722021-06-09 10:53:51 -0700577 return credentials.password();
578 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100579
Ed Tanous22db1722021-06-09 10:53:51 -0700580 SecureBuffer pack(FormatterFunc formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100581 {
Ed Tanous22db1722021-06-09 10:53:51 -0700582 SecureBuffer packed{new Buffer{}};
583 if (formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100584 {
Ed Tanous22db1722021-06-09 10:53:51 -0700585 formatter(credentials.user(), credentials.password(), *packed);
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100586 }
587
Ed Tanous22db1722021-06-09 10:53:51 -0700588 return packed;
589 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100590
Ed Tanous22db1722021-06-09 10:53:51 -0700591 private:
592 Credentials credentials;
593};
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100594
Ed Tanous22db1722021-06-09 10:53:51 -0700595// Wrapper for boost::async_pipe ensuring proper pipe cleanup
596template <typename Buffer>
597class Pipe
598{
599 public:
600 using unix_fd = sdbusplus::message::unix_fd;
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100601
Ed Tanous22db1722021-06-09 10:53:51 -0700602 Pipe(boost::asio::io_context& io, Buffer&& buffer) :
603 impl(io), buffer{std::move(buffer)}
604 {}
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100605
Ed Tanous22db1722021-06-09 10:53:51 -0700606 ~Pipe()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100607 {
Ed Tanous22db1722021-06-09 10:53:51 -0700608 // Named pipe needs to be explicitly removed
609 impl.close();
610 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100611
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800612 Pipe(const Pipe&) = delete;
613 Pipe(Pipe&&) = delete;
614 Pipe& operator=(const Pipe&) = delete;
615 Pipe& operator=(Pipe&&) = delete;
616
Ed Tanous22db1722021-06-09 10:53:51 -0700617 unix_fd fd()
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200618 {
Ed Tanous22db1722021-06-09 10:53:51 -0700619 return unix_fd{impl.native_source()};
620 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100621
Ed Tanous22db1722021-06-09 10:53:51 -0700622 template <typename WriteHandler>
623 void asyncWrite(WriteHandler&& handler)
624 {
625 impl.async_write_some(data(), std::forward<WriteHandler>(handler));
626 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100627
Ed Tanous22db1722021-06-09 10:53:51 -0700628 private:
629 // Specialization for pointer types
630 template <typename B = Buffer>
631 typename std::enable_if<boost::has_dereference<B>::value,
632 boost::asio::const_buffer>::type
633 data()
634 {
635 return boost::asio::buffer(*buffer);
636 }
637
638 template <typename B = Buffer>
639 typename std::enable_if<!boost::has_dereference<B>::value,
640 boost::asio::const_buffer>::type
641 data()
642 {
643 return boost::asio::buffer(buffer);
644 }
645
646 const std::string name;
647 boost::process::async_pipe impl;
648 Buffer buffer;
649};
650
651/**
652 * @brief Function transceives data with dbus directly.
653 *
654 * All BMC state properties will be retrieved before sending reset request.
655 */
656inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
657 const std::string& service, const std::string& name,
658 const std::string& imageUrl, const bool rw,
659 std::string&& userName, std::string&& password)
660{
661 using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
662 constexpr const size_t secretLimit = 1024;
663
664 std::shared_ptr<SecurePipe> secretPipe;
Ed Tanous168e20c2021-12-13 14:39:53 -0800665 dbus::utility::DbusVariantType unixFd = -1;
Ed Tanous22db1722021-06-09 10:53:51 -0700666
667 if (!userName.empty() || !password.empty())
668 {
669 // Encapsulate in safe buffer
670 CredentialsProvider credentials(std::move(userName),
671 std::move(password));
672
673 // Payload must contain data + NULL delimiters
674 if (credentials.user().size() + credentials.password().size() + 2 >
675 secretLimit)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100676 {
Ed Tanous22db1722021-06-09 10:53:51 -0700677 BMCWEB_LOG_ERROR << "Credentials too long to handle";
678 messages::unrecognizedRequestBody(asyncResp->res);
679 return;
680 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100681
Ed Tanous22db1722021-06-09 10:53:51 -0700682 // Pack secret
683 auto secret = credentials.pack(
684 [](const auto& user, const auto& pass, auto& buff) {
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100685 std::copy(user.begin(), user.end(), std::back_inserter(buff));
686 buff.push_back('\0');
687 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
688 buff.push_back('\0');
689 });
690
Ed Tanous22db1722021-06-09 10:53:51 -0700691 // Open pipe
692 secretPipe = std::make_shared<SecurePipe>(
693 crow::connections::systemBus->get_io_context(), std::move(secret));
694 unixFd = secretPipe->fd();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100695
Ed Tanous22db1722021-06-09 10:53:51 -0700696 // Pass secret over pipe
697 secretPipe->asyncWrite(
698 [asyncResp](const boost::system::error_code& ec, std::size_t) {
699 if (ec)
700 {
701 BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
702 messages::internalError(asyncResp->res);
703 }
704 });
705 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100706
Ed Tanous22db1722021-06-09 10:53:51 -0700707 crow::connections::systemBus->async_method_call(
708 [asyncResp, secretPipe](const boost::system::error_code ec,
709 bool success) {
710 if (ec)
711 {
712 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
713 messages::internalError(asyncResp->res);
714 }
715 else if (!success)
716 {
717 BMCWEB_LOG_ERROR << "Service responded with error";
718 messages::generalError(asyncResp->res);
719 }
720 },
721 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
722 "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
723 unixFd);
724}
725
726/**
727 * @brief Function transceives data with dbus directly.
728 *
729 * All BMC state properties will be retrieved before sending reset request.
730 */
731inline void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
732 const std::string& service, const std::string& name,
733 bool legacy)
734{
735
736 // Legacy mount requires parameter with image
737 if (legacy)
738 {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100739 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700740 [asyncResp](const boost::system::error_code ec) {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100741 if (ec)
742 {
743 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700744
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100745 messages::internalError(asyncResp->res);
Ed Tanous22db1722021-06-09 10:53:51 -0700746 return;
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100747 }
748 },
749 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
Ed Tanous22db1722021-06-09 10:53:51 -0700750 "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200751 }
Ed Tanous22db1722021-06-09 10:53:51 -0700752 else // proxy
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200753 {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200754 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700755 [asyncResp](const boost::system::error_code ec) {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200756 if (ec)
757 {
Ed Tanous22db1722021-06-09 10:53:51 -0700758 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
759
zhanghch058d1b46d2021-04-01 11:18:24 +0800760 messages::internalError(asyncResp->res);
Ed Tanous22db1722021-06-09 10:53:51 -0700761 return;
762 }
763 },
764 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
765 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
766 }
767}
768
Ed Tanous98be3e32021-09-16 15:05:36 -0700769struct InsertMediaActionParams
770{
771 std::string imageUrl;
772 std::optional<std::string> userName;
773 std::optional<std::string> password;
774 std::optional<std::string> transferMethod;
775 std::optional<std::string> transferProtocolType;
776 std::optional<bool> writeProtected = true;
777 std::optional<bool> inserted;
778};
779
Ed Tanous22db1722021-06-09 10:53:51 -0700780inline void requestNBDVirtualMediaRoutes(App& app)
781{
George Liu0fda0f12021-11-16 10:06:17 +0800782 BMCWEB_ROUTE(
783 app,
784 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
Ed Tanoused398212021-06-09 17:05:54 -0700785 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -0700786 .methods(boost::beast::http::verb::post)(
787 [](const crow::Request& req,
788 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
789 const std::string& name, const std::string& resName) {
790 if (name != "bmc")
791 {
792 messages::resourceNotFound(asyncResp->res,
793 "VirtualMedia.Insert", resName);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200794
795 return;
796 }
Ed Tanous98be3e32021-09-16 15:05:36 -0700797 InsertMediaActionParams actionParams;
798
799 // Read obligatory parameters (url of
800 // image)
801 if (!json_util::readJson(
802 req, asyncResp->res, "Image", actionParams.imageUrl,
803 "WriteProtected", actionParams.writeProtected,
804 "UserName", actionParams.userName, "Password",
805 actionParams.password, "Inserted",
806 actionParams.inserted, "TransferMethod",
807 actionParams.transferMethod, "TransferProtocolType",
808 actionParams.transferProtocolType))
809 {
810 BMCWEB_LOG_DEBUG << "Image is not provided";
811 return;
812 }
813
814 bool paramsValid = validateParams(
815 asyncResp->res, actionParams.imageUrl,
816 actionParams.inserted, actionParams.transferMethod,
817 actionParams.transferProtocolType);
818
819 if (paramsValid == false)
820 {
821 return;
822 }
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200823
824 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700825 [asyncResp, actionParams,
Ed Tanous22db1722021-06-09 10:53:51 -0700826 resName](const boost::system::error_code ec,
Ed Tanous98be3e32021-09-16 15:05:36 -0700827 const GetObjectType& getObjectType) mutable {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200828 if (ec)
829 {
Ed Tanous22db1722021-06-09 10:53:51 -0700830 BMCWEB_LOG_ERROR
831 << "ObjectMapper::GetObject call failed: "
832 << ec;
833 messages::internalError(asyncResp->res);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200834
835 return;
836 }
Ed Tanous22db1722021-06-09 10:53:51 -0700837 std::string service = getObjectType.begin()->first;
838 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200839
Ed Tanous22db1722021-06-09 10:53:51 -0700840 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700841 [service, resName, actionParams,
Ed Tanous22db1722021-06-09 10:53:51 -0700842 asyncResp](const boost::system::error_code ec,
Ed Tanous711ac7a2021-12-20 09:34:41 -0800843 dbus::utility::ManagedObjectType&
844 subtree) mutable {
Ed Tanous22db1722021-06-09 10:53:51 -0700845 if (ec)
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200846 {
Ed Tanous22db1722021-06-09 10:53:51 -0700847 BMCWEB_LOG_DEBUG << "DBUS response error";
848
849 return;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200850 }
851
Ed Tanous22db1722021-06-09 10:53:51 -0700852 for (const auto& object : subtree)
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200853 {
Ed Tanous22db1722021-06-09 10:53:51 -0700854 const std::string& path =
855 static_cast<const std::string&>(
856 object.first);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200857
Ed Tanous22db1722021-06-09 10:53:51 -0700858 std::size_t lastIndex = path.rfind('/');
859 if (lastIndex == std::string::npos)
860 {
861 continue;
862 }
863
864 lastIndex += 1;
865
866 if (path.substr(lastIndex) == resName)
867 {
868 lastIndex = path.rfind("Proxy");
869 if (lastIndex != std::string::npos)
870 {
871 // Not possible in proxy mode
872 BMCWEB_LOG_DEBUG
873 << "InsertMedia not "
874 "allowed in proxy mode";
875 messages::resourceNotFound(
876 asyncResp->res,
877 "VirtualMedia.InsertMedia",
878 resName);
879
880 return;
881 }
882
883 lastIndex = path.rfind("Legacy");
884 if (lastIndex == std::string::npos)
885 {
886 continue;
887 }
888
Ed Tanous22db1722021-06-09 10:53:51 -0700889 // manager is irrelevant for
890 // VirtualMedia dbus calls
Ed Tanous98be3e32021-09-16 15:05:36 -0700891 doMountVmLegacy(
892 asyncResp, service, resName,
893 actionParams.imageUrl,
894 !(*actionParams.writeProtected),
895 std::move(*actionParams.userName),
896 std::move(*actionParams.password));
Ed Tanous22db1722021-06-09 10:53:51 -0700897
898 return;
899 }
900 }
901 BMCWEB_LOG_DEBUG << "Parent item not found";
902 messages::resourceNotFound(
903 asyncResp->res, "VirtualMedia", resName);
904 },
905 service, "/xyz/openbmc_project/VirtualMedia",
906 "org.freedesktop.DBus.ObjectManager",
907 "GetManagedObjects");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200908 },
Ed Tanous22db1722021-06-09 10:53:51 -0700909 "xyz.openbmc_project.ObjectMapper",
910 "/xyz/openbmc_project/object_mapper",
911 "xyz.openbmc_project.ObjectMapper", "GetObject",
912 "/xyz/openbmc_project/VirtualMedia",
913 std::array<const char*, 0>());
914 });
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200915
George Liu0fda0f12021-11-16 10:06:17 +0800916 BMCWEB_ROUTE(
917 app,
918 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
Ed Tanoused398212021-06-09 17:05:54 -0700919 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -0700920 .methods(boost::beast::http::verb::post)(
Ed Tanous98be3e32021-09-16 15:05:36 -0700921 [](const crow::Request&,
Ed Tanous22db1722021-06-09 10:53:51 -0700922 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
923 const std::string& name, const std::string& resName) {
924 if (name != "bmc")
925 {
926 messages::resourceNotFound(asyncResp->res,
927 "VirtualMedia.Eject", resName);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200928
Ed Tanous22db1722021-06-09 10:53:51 -0700929 return;
930 }
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200931
Ed Tanous22db1722021-06-09 10:53:51 -0700932 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700933 [asyncResp, resName](const boost::system::error_code ec,
934 const GetObjectType& getObjectType) {
Ed Tanous22db1722021-06-09 10:53:51 -0700935 if (ec)
936 {
937 BMCWEB_LOG_ERROR
938 << "ObjectMapper::GetObject call failed: "
939 << ec;
940 messages::internalError(asyncResp->res);
941
942 return;
943 }
944 std::string service = getObjectType.begin()->first;
945 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
946
947 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700948 [resName, service, asyncResp{asyncResp}](
Ed Tanous22db1722021-06-09 10:53:51 -0700949 const boost::system::error_code ec,
Ed Tanous711ac7a2021-12-20 09:34:41 -0800950 dbus::utility::ManagedObjectType& subtree) {
Ed Tanous22db1722021-06-09 10:53:51 -0700951 if (ec)
952 {
953 BMCWEB_LOG_DEBUG << "DBUS response error";
954
955 return;
956 }
957
958 for (const auto& object : subtree)
959 {
960 const std::string& path =
961 static_cast<const std::string&>(
962 object.first);
963
964 std::size_t lastIndex = path.rfind('/');
965 if (lastIndex == std::string::npos)
966 {
967 continue;
968 }
969
970 lastIndex += 1;
971
972 if (path.substr(lastIndex) == resName)
973 {
974 lastIndex = path.rfind("Proxy");
975 if (lastIndex != std::string::npos)
976 {
977 // Proxy mode
978 doVmAction(asyncResp, service,
979 resName, false);
980 }
981
982 lastIndex = path.rfind("Legacy");
983 if (lastIndex != std::string::npos)
984 {
985 // Legacy mode
986 doVmAction(asyncResp, service,
987 resName, true);
988 }
989
990 return;
991 }
992 }
993 BMCWEB_LOG_DEBUG << "Parent item not found";
994 messages::resourceNotFound(
995 asyncResp->res, "VirtualMedia", resName);
996 },
997 service, "/xyz/openbmc_project/VirtualMedia",
998 "org.freedesktop.DBus.ObjectManager",
999 "GetManagedObjects");
1000 },
1001 "xyz.openbmc_project.ObjectMapper",
1002 "/xyz/openbmc_project/object_mapper",
1003 "xyz.openbmc_project.ObjectMapper", "GetObject",
1004 "/xyz/openbmc_project/VirtualMedia",
1005 std::array<const char*, 0>());
1006 });
1007 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
Ed Tanoused398212021-06-09 17:05:54 -07001008 .privileges(redfish::privileges::getVirtualMediaCollection)
Ed Tanous22db1722021-06-09 10:53:51 -07001009 .methods(boost::beast::http::verb::get)(
1010 [](const crow::Request& /* req */,
1011 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1012 const std::string& name) {
1013 if (name != "bmc")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001014 {
Ed Tanous22db1722021-06-09 10:53:51 -07001015 messages::resourceNotFound(asyncResp->res, "VirtualMedia",
1016 name);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001017
1018 return;
1019 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001020
Ed Tanous22db1722021-06-09 10:53:51 -07001021 asyncResp->res.jsonValue["@odata.type"] =
1022 "#VirtualMediaCollection.VirtualMediaCollection";
1023 asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
1024 asyncResp->res.jsonValue["@odata.id"] =
1025 "/redfish/v1/Managers/" + name + "/VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001026
Ed Tanous22db1722021-06-09 10:53:51 -07001027 crow::connections::systemBus->async_method_call(
1028 [asyncResp, name](const boost::system::error_code ec,
1029 const GetObjectType& getObjectType) {
1030 if (ec)
1031 {
1032 BMCWEB_LOG_ERROR
1033 << "ObjectMapper::GetObject call failed: "
1034 << ec;
1035 messages::internalError(asyncResp->res);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001036
Ed Tanous22db1722021-06-09 10:53:51 -07001037 return;
1038 }
1039 std::string service = getObjectType.begin()->first;
1040 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001041
Ed Tanous22db1722021-06-09 10:53:51 -07001042 getVmResourceList(asyncResp, service, name);
1043 },
1044 "xyz.openbmc_project.ObjectMapper",
1045 "/xyz/openbmc_project/object_mapper",
1046 "xyz.openbmc_project.ObjectMapper", "GetObject",
1047 "/xyz/openbmc_project/VirtualMedia",
1048 std::array<const char*, 0>());
1049 });
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001050
Ed Tanous22db1722021-06-09 10:53:51 -07001051 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001052 .privileges(redfish::privileges::getVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -07001053 .methods(boost::beast::http::verb::get)(
1054 [](const crow::Request& /* req */,
1055 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1056 const std::string& name, const std::string& resName) {
1057 if (name != "bmc")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001058 {
Ed Tanous22db1722021-06-09 10:53:51 -07001059 messages::resourceNotFound(asyncResp->res, "VirtualMedia",
1060 resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001061
1062 return;
1063 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001064
Ed Tanous22db1722021-06-09 10:53:51 -07001065 crow::connections::systemBus->async_method_call(
1066 [asyncResp, name,
1067 resName](const boost::system::error_code ec,
1068 const GetObjectType& getObjectType) {
1069 if (ec)
1070 {
1071 BMCWEB_LOG_ERROR
1072 << "ObjectMapper::GetObject call failed: "
1073 << ec;
1074 messages::internalError(asyncResp->res);
1075
1076 return;
1077 }
1078 std::string service = getObjectType.begin()->first;
1079 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1080
1081 getVmData(asyncResp, service, name, resName);
1082 },
1083 "xyz.openbmc_project.ObjectMapper",
1084 "/xyz/openbmc_project/object_mapper",
1085 "xyz.openbmc_project.ObjectMapper", "GetObject",
1086 "/xyz/openbmc_project/VirtualMedia",
1087 std::array<const char*, 0>());
1088 });
1089}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001090
1091} // namespace redfish