blob: 7159be15a352d4d7c1205cb889440942b25ce08f [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
Ed Tanousb9d36b42022-02-26 21:42:46 -080018#include <account_service.hpp>
John Edward Broadbent7e860f12021-04-08 15:57:16 -070019#include <app.hpp>
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +010020#include <boost/process/async_pipe.hpp>
21#include <boost/type_traits/has_dereference.hpp>
Anna Platash9e319cf2020-11-17 10:18:31 +010022#include <boost/url/url_view.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070023#include <registries/privilege_registry.hpp>
Ed Tanousb9d36b42022-02-26 21:42:46 -080024#include <utils/json_utils.hpp>
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020025
26namespace redfish
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020027{
Anna Platash9e319cf2020-11-17 10:18:31 +010028/**
29 * @brief Function extracts transfer protocol name from URI.
30 */
Ed Tanous67df0732021-10-26 11:23:56 -070031inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
32{
33 boost::urls::result<boost::urls::url_view> url =
34 boost::urls::parse_uri(boost::string_view(imageUri));
35 if (!url)
36 {
37 return "None";
38 }
39 boost::string_view scheme = url->scheme();
40 if (scheme == "smb")
41 {
42 return "CIFS";
43 }
44 if (scheme == "https")
45 {
46 return "HTTPS";
47 }
48
49 return "None";
50}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020051
52/**
53 * @brief Read all known properties from VM object interfaces
54 */
Ed Tanous22db1722021-06-09 10:53:51 -070055inline void
Ed Tanous711ac7a2021-12-20 09:34:41 -080056 vmParseInterfaceObject(const dbus::utility::DBusInteracesMap& interface,
zhanghch058d1b46d2021-04-01 11:18:24 +080057 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020058{
Ed Tanous711ac7a2021-12-20 09:34:41 -080059 for (const auto& [interface, values] : interface)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020060 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080061 if (interface == "xyz.openbmc_project.VirtualMedia.MountPoint")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020062 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080063 for (const auto& [property, value] : values)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020064 {
Ed Tanous711ac7a2021-12-20 09:34:41 -080065 if (property == "EndpointId")
66 {
67 const std::string* endpointIdValue =
68 std::get_if<std::string>(&value);
69 if (endpointIdValue == nullptr)
70 {
71 continue;
72 }
73 if (!endpointIdValue->empty())
74 {
75 // Proxy mode
76 aResp->res
77 .jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
78 *endpointIdValue;
79 aResp->res.jsonValue["TransferProtocolType"] = "OEM";
80 }
81 }
82 if (property == "ImageURL")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020083 {
Anna Platash9e319cf2020-11-17 10:18:31 +010084 const std::string* imageUrlValue =
Ed Tanous711ac7a2021-12-20 09:34:41 -080085 std::get_if<std::string>(&value);
Ed Tanous26f69762022-01-25 09:49:11 -080086 if (imageUrlValue != nullptr && !imageUrlValue->empty())
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +010087 {
Anna Platash9e319cf2020-11-17 10:18:31 +010088 std::filesystem::path filePath = *imageUrlValue;
89 if (!filePath.has_filename())
90 {
91 // this will handle https share, which not
92 // necessarily has to have filename given.
93 aResp->res.jsonValue["ImageName"] = "";
94 }
95 else
96 {
97 aResp->res.jsonValue["ImageName"] =
98 filePath.filename();
99 }
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100100
Anna Platash9e319cf2020-11-17 10:18:31 +0100101 aResp->res.jsonValue["Image"] = *imageUrlValue;
Anna Platash9e319cf2020-11-17 10:18:31 +0100102 aResp->res.jsonValue["TransferProtocolType"] =
103 getTransferProtocolTypeFromUri(*imageUrlValue);
104
Ed Tanous711ac7a2021-12-20 09:34:41 -0800105 aResp->res.jsonValue["ConnectedVia"] = "URI";
Anna Platash9e319cf2020-11-17 10:18:31 +0100106 }
107 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800108 if (property == "WriteProtected")
Anna Platash9e319cf2020-11-17 10:18:31 +0100109 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800110 const bool* writeProtectedValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800111 if (writeProtectedValue != nullptr)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200112 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100113 aResp->res.jsonValue["WriteProtected"] =
114 *writeProtectedValue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200115 }
116 }
117 }
118 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800119 if (interface == "xyz.openbmc_project.VirtualMedia.Process")
120 {
121 for (const auto& [property, value] : values)
122 {
123 if (property == "Active")
124 {
125 const bool* activeValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800126 if (activeValue == nullptr)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800127 {
128 BMCWEB_LOG_DEBUG << "Value Active not found";
129 return;
130 }
131 aResp->res.jsonValue["Inserted"] = *activeValue;
132
Ed Tanouse05aec52022-01-25 10:28:56 -0800133 if (*activeValue)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800134 {
135 aResp->res.jsonValue["ConnectedVia"] = "Applet";
136 }
137 }
138 }
139 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200140 }
141}
142
143/**
144 * @brief Fill template for Virtual Media Item.
145 */
Ed Tanous22db1722021-06-09 10:53:51 -0700146inline nlohmann::json vmItemTemplate(const std::string& name,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500147 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200148{
149 nlohmann::json item;
Ed Tanous22db1722021-06-09 10:53:51 -0700150
151 std::string id = "/redfish/v1/Managers/";
152 id += name;
153 id += "/VirtualMedia/";
154 id += resName;
155 item["@odata.id"] = std::move(id);
156
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100157 item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200158 item["Name"] = "Virtual Removable Media";
159 item["Id"] = resName;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200160 item["WriteProtected"] = true;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200161 item["MediaTypes"] = {"CD", "USBStick"};
162 item["TransferMethod"] = "Stream";
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100163 item["Oem"]["OpenBMC"]["@odata.type"] =
164 "#OemVirtualMedia.v1_0_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200165
166 return item;
167}
168
169/**
170 * @brief Fills collection data
171 */
Ed Tanous22db1722021-06-09 10:53:51 -0700172inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500173 const std::string& service,
174 const std::string& name)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200175{
176 BMCWEB_LOG_DEBUG << "Get available Virtual Media resources.";
177 crow::connections::systemBus->async_method_call(
Ed Tanous711ac7a2021-12-20 09:34:41 -0800178 [name,
179 aResp{std::move(aResp)}](const boost::system::error_code ec,
180 dbus::utility::ManagedObjectType& subtree) {
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200181 if (ec)
182 {
183 BMCWEB_LOG_DEBUG << "DBUS response error";
184 return;
185 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500186 nlohmann::json& members = aResp->res.jsonValue["Members"];
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200187 members = nlohmann::json::array();
188
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500189 for (const auto& object : subtree)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200190 {
191 nlohmann::json item;
Ed Tanous2dfd18e2020-12-18 00:41:31 +0000192 std::string path = object.first.filename();
193 if (path.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200194 {
195 continue;
196 }
197
Ed Tanous22db1722021-06-09 10:53:51 -0700198 std::string id = "/redfish/v1/Managers/";
199 id += name;
200 id += "/VirtualMedia/";
201 id += path;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200202
Ed Tanous22db1722021-06-09 10:53:51 -0700203 item["@odata.id"] = std::move(id);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200204 members.emplace_back(std::move(item));
205 }
206 aResp->res.jsonValue["Members@odata.count"] = members.size();
207 },
208 service, "/xyz/openbmc_project/VirtualMedia",
209 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
210}
211
212/**
213 * @brief Fills data for specific resource
214 */
Ed Tanous22db1722021-06-09 10:53:51 -0700215inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500216 const std::string& service, const std::string& name,
217 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200218{
219 BMCWEB_LOG_DEBUG << "Get Virtual Media resource data.";
220
221 crow::connections::systemBus->async_method_call(
Ed Tanous914e2d52022-01-07 11:38:34 -0800222 [resName, name,
223 aResp](const boost::system::error_code ec,
224 const dbus::utility::ManagedObjectType& subtree) {
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200225 if (ec)
226 {
227 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200228
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200229 return;
230 }
231
Ed Tanous914e2d52022-01-07 11:38:34 -0800232 for (const auto& item : subtree)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200233 {
Ed Tanous2dfd18e2020-12-18 00:41:31 +0000234 std::string thispath = item.first.filename();
235 if (thispath.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200236 {
237 continue;
238 }
239
Ed Tanous2dfd18e2020-12-18 00:41:31 +0000240 if (thispath != resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200241 {
242 continue;
243 }
244
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200245 // "Legacy"/"Proxy"
246 auto mode = item.first.parent_path();
247 // "VirtualMedia"
248 auto type = mode.parent_path();
249 if (mode.filename().empty() || type.filename().empty())
250 {
251 continue;
252 }
253
254 if (type.filename() != "VirtualMedia")
255 {
256 continue;
257 }
258
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200259 aResp->res.jsonValue = vmItemTemplate(name, resName);
Ed Tanous22db1722021-06-09 10:53:51 -0700260 std::string actionsId = "/redfish/v1/Managers/";
261 actionsId += name;
262 actionsId += "/VirtualMedia/";
263 actionsId += resName;
264 actionsId += "/Actions";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200265
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200266 // Check if dbus path is Legacy type
Przemyslaw Czarnowski1a6258d2021-04-14 11:02:46 +0200267 if (mode.filename() == "Legacy")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200268 {
269 aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
270 ["target"] =
Ed Tanous22db1722021-06-09 10:53:51 -0700271 actionsId + "/VirtualMedia.InsertMedia";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200272 }
273
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200274 vmParseInterfaceObject(item.second, aResp);
275
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200276 aResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"]
277 ["target"] =
Ed Tanous22db1722021-06-09 10:53:51 -0700278 actionsId + "/VirtualMedia.EjectMedia";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200279
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200280 return;
281 }
282
283 messages::resourceNotFound(
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100284 aResp->res, "#VirtualMedia.v1_3_0.VirtualMedia", resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200285 },
286 service, "/xyz/openbmc_project/VirtualMedia",
287 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
288}
289
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200290/**
Ed Tanous22db1722021-06-09 10:53:51 -0700291 * @brief Transfer protocols supported for InsertMedia action.
292 *
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200293 */
Ed Tanous22db1722021-06-09 10:53:51 -0700294enum class TransferProtocol
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200295{
Ed Tanous22db1722021-06-09 10:53:51 -0700296 https,
297 smb,
298 invalid
299};
300
301/**
302 * @brief Function extracts transfer protocol type from URI.
303 *
304 */
Ed Tanous67df0732021-10-26 11:23:56 -0700305inline std::optional<TransferProtocol>
Ed Tanousace85d62021-10-26 12:45:59 -0700306 getTransferProtocolFromUri(const boost::urls::url_view& imageUri)
Ed Tanous67df0732021-10-26 11:23:56 -0700307{
Ed Tanousace85d62021-10-26 12:45:59 -0700308 boost::string_view scheme = imageUri.scheme();
Ed Tanous67df0732021-10-26 11:23:56 -0700309 if (scheme == "smb")
310 {
311 return TransferProtocol::smb;
312 }
313 if (scheme == "https")
314 {
315 return TransferProtocol::https;
316 }
317 if (!scheme.empty())
318 {
319 return TransferProtocol::invalid;
320 }
321
322 return {};
323}
Ed Tanous22db1722021-06-09 10:53:51 -0700324
325/**
326 * @brief Function convert transfer protocol from string param.
327 *
328 */
329inline std::optional<TransferProtocol> getTransferProtocolFromParam(
330 const std::optional<std::string>& transferProtocolType)
331{
332 if (transferProtocolType == std::nullopt)
Agata Olenderc6f4e012020-03-11 15:19:07 +0100333 {
Ed Tanous22db1722021-06-09 10:53:51 -0700334 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100335 }
336
Ed Tanous22db1722021-06-09 10:53:51 -0700337 if (*transferProtocolType == "CIFS")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200338 {
Ed Tanous22db1722021-06-09 10:53:51 -0700339 return TransferProtocol::smb;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200340 }
341
Ed Tanous22db1722021-06-09 10:53:51 -0700342 if (*transferProtocolType == "HTTPS")
343 {
344 return TransferProtocol::https;
345 }
346
347 return TransferProtocol::invalid;
348}
349
350/**
351 * @brief Function extends URI with transfer protocol type.
352 *
353 */
354inline std::string
355 getUriWithTransferProtocol(const std::string& imageUri,
356 const TransferProtocol& transferProtocol)
357{
358 if (transferProtocol == TransferProtocol::smb)
359 {
360 return "smb://" + imageUri;
361 }
362
363 if (transferProtocol == TransferProtocol::https)
364 {
365 return "https://" + imageUri;
366 }
367
368 return imageUri;
369}
370
371/**
372 * @brief Function validate parameters of insert media request.
373 *
374 */
375inline bool
376 validateParams(crow::Response& res, std::string& imageUrl,
377 const std::optional<bool>& inserted,
378 const std::optional<std::string>& transferMethod,
379 const std::optional<std::string>& transferProtocolType)
380{
381 BMCWEB_LOG_DEBUG << "Validation started";
382 // required param imageUrl must not be empty
383 if (imageUrl.empty())
384 {
385 BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
386
387 messages::propertyValueFormatError(res, "<empty>", "Image");
388
389 return false;
390 }
391
392 // optional param inserted must be true
Ed Tanouse05aec52022-01-25 10:28:56 -0800393 if ((inserted != std::nullopt) && !*inserted)
Ed Tanous22db1722021-06-09 10:53:51 -0700394 {
395 BMCWEB_LOG_ERROR
396 << "Request action optional parameter Inserted must be true.";
397
398 messages::actionParameterNotSupported(res, "Inserted", "InsertMedia");
399
400 return false;
401 }
402
403 // optional param transferMethod must be stream
404 if ((transferMethod != std::nullopt) && (*transferMethod != "Stream"))
405 {
406 BMCWEB_LOG_ERROR << "Request action optional parameter "
407 "TransferMethod must be Stream.";
408
409 messages::actionParameterNotSupported(res, "TransferMethod",
410 "InsertMedia");
411
412 return false;
413 }
Ed Tanousace85d62021-10-26 12:45:59 -0700414 boost::urls::result<boost::urls::url_view> url =
415 boost::urls::parse_uri(boost::string_view(imageUrl));
416 if (!url)
417 {
418 messages::resourceAtUriInUnknownFormat(res, *url);
419 return {};
420 }
Ed Tanous22db1722021-06-09 10:53:51 -0700421 std::optional<TransferProtocol> uriTransferProtocolType =
Ed Tanousace85d62021-10-26 12:45:59 -0700422 getTransferProtocolFromUri(*url);
Ed Tanous22db1722021-06-09 10:53:51 -0700423
424 std::optional<TransferProtocol> paramTransferProtocolType =
425 getTransferProtocolFromParam(transferProtocolType);
426
427 // ImageUrl does not contain valid protocol type
428 if (*uriTransferProtocolType == TransferProtocol::invalid)
429 {
430 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
431 "contain specified protocol type from list: "
432 "(smb, https).";
433
Ed Tanousace85d62021-10-26 12:45:59 -0700434 messages::resourceAtUriInUnknownFormat(res, *url);
Ed Tanous22db1722021-06-09 10:53:51 -0700435
436 return false;
437 }
438
439 // transferProtocolType should contain value from list
440 if (*paramTransferProtocolType == TransferProtocol::invalid)
441 {
442 BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
443 "must be provided with value from list: "
444 "(CIFS, HTTPS).";
445
446 messages::propertyValueNotInList(res, *transferProtocolType,
447 "TransferProtocolType");
448 return false;
449 }
450
451 // valid transfer protocol not provided either with URI nor param
452 if ((uriTransferProtocolType == std::nullopt) &&
453 (paramTransferProtocolType == std::nullopt))
454 {
455 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
456 "contain specified protocol type or param "
457 "TransferProtocolType must be provided.";
458
Ed Tanousace85d62021-10-26 12:45:59 -0700459 messages::resourceAtUriInUnknownFormat(res, *url);
Ed Tanous22db1722021-06-09 10:53:51 -0700460
461 return false;
462 }
463
464 // valid transfer protocol provided both with URI and param
465 if ((paramTransferProtocolType != std::nullopt) &&
466 (uriTransferProtocolType != std::nullopt))
467 {
468 // check if protocol is the same for URI and param
469 if (*paramTransferProtocolType != *uriTransferProtocolType)
470 {
471 BMCWEB_LOG_ERROR << "Request action parameter "
472 "TransferProtocolType must contain the "
473 "same protocol type as protocol type "
474 "provided with param imageUrl.";
475
476 messages::actionParameterValueTypeError(res, *transferProtocolType,
477 "TransferProtocolType",
478 "InsertMedia");
479
480 return false;
481 }
482 }
483
484 // validation passed
485 // add protocol to URI if needed
486 if (uriTransferProtocolType == std::nullopt)
487 {
488 imageUrl =
489 getUriWithTransferProtocol(imageUrl, *paramTransferProtocolType);
490 }
491
492 return true;
493}
494
495template <typename T>
496static void secureCleanup(T& value)
497{
Ed Tanous4ecc6182022-01-07 09:36:26 -0800498 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
Ed Tanous22db1722021-06-09 10:53:51 -0700499 auto raw = const_cast<typename T::value_type*>(value.data());
500 explicit_bzero(raw, value.size() * sizeof(*raw));
501}
502
503class Credentials
504{
505 public:
506 Credentials(std::string&& user, std::string&& password) :
507 userBuf(std::move(user)), passBuf(std::move(password))
508 {}
509
510 ~Credentials()
511 {
512 secureCleanup(userBuf);
513 secureCleanup(passBuf);
514 }
515
516 const std::string& user()
517 {
518 return userBuf;
519 }
520
521 const std::string& password()
522 {
523 return passBuf;
524 }
525
526 Credentials() = delete;
527 Credentials(const Credentials&) = delete;
528 Credentials& operator=(const Credentials&) = delete;
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800529 Credentials(Credentials&&) = delete;
530 Credentials& operator=(Credentials&&) = delete;
Ed Tanous22db1722021-06-09 10:53:51 -0700531
532 private:
533 std::string userBuf;
534 std::string passBuf;
535};
536
537class CredentialsProvider
538{
539 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500540 template <typename T>
Ed Tanous22db1722021-06-09 10:53:51 -0700541 struct Deleter
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100542 {
Ed Tanous22db1722021-06-09 10:53:51 -0700543 void operator()(T* buff) const
544 {
545 if (buff)
546 {
547 secureCleanup(*buff);
548 delete buff;
549 }
550 }
551 };
552
553 using Buffer = std::vector<char>;
554 using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
555 // Using explicit definition instead of std::function to avoid implicit
556 // conversions eg. stack copy instead of reference
557 using FormatterFunc = void(const std::string& username,
558 const std::string& password, Buffer& dest);
559
560 CredentialsProvider(std::string&& user, std::string&& password) :
561 credentials(std::move(user), std::move(password))
562 {}
563
564 const std::string& user()
565 {
566 return credentials.user();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100567 }
568
Ed Tanous22db1722021-06-09 10:53:51 -0700569 const std::string& password()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100570 {
Ed Tanous22db1722021-06-09 10:53:51 -0700571 return credentials.password();
572 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100573
Ed Tanous22db1722021-06-09 10:53:51 -0700574 SecureBuffer pack(FormatterFunc formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100575 {
Ed Tanous22db1722021-06-09 10:53:51 -0700576 SecureBuffer packed{new Buffer{}};
Ed Tanouse662eae2022-01-25 10:39:19 -0800577 if (formatter != nullptr)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100578 {
Ed Tanous22db1722021-06-09 10:53:51 -0700579 formatter(credentials.user(), credentials.password(), *packed);
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100580 }
581
Ed Tanous22db1722021-06-09 10:53:51 -0700582 return packed;
583 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100584
Ed Tanous22db1722021-06-09 10:53:51 -0700585 private:
586 Credentials credentials;
587};
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100588
Ed Tanous22db1722021-06-09 10:53:51 -0700589// Wrapper for boost::async_pipe ensuring proper pipe cleanup
590template <typename Buffer>
591class Pipe
592{
593 public:
594 using unix_fd = sdbusplus::message::unix_fd;
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100595
Ed Tanous22db1722021-06-09 10:53:51 -0700596 Pipe(boost::asio::io_context& io, Buffer&& buffer) :
597 impl(io), buffer{std::move(buffer)}
598 {}
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100599
Ed Tanous22db1722021-06-09 10:53:51 -0700600 ~Pipe()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100601 {
Ed Tanous22db1722021-06-09 10:53:51 -0700602 // Named pipe needs to be explicitly removed
603 impl.close();
604 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100605
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800606 Pipe(const Pipe&) = delete;
607 Pipe(Pipe&&) = delete;
608 Pipe& operator=(const Pipe&) = delete;
609 Pipe& operator=(Pipe&&) = delete;
610
Ed Tanous22db1722021-06-09 10:53:51 -0700611 unix_fd fd()
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200612 {
Ed Tanous22db1722021-06-09 10:53:51 -0700613 return unix_fd{impl.native_source()};
614 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100615
Ed Tanous22db1722021-06-09 10:53:51 -0700616 template <typename WriteHandler>
617 void asyncWrite(WriteHandler&& handler)
618 {
619 impl.async_write_some(data(), std::forward<WriteHandler>(handler));
620 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100621
Ed Tanous22db1722021-06-09 10:53:51 -0700622 private:
623 // Specialization for pointer types
624 template <typename B = Buffer>
625 typename std::enable_if<boost::has_dereference<B>::value,
626 boost::asio::const_buffer>::type
627 data()
628 {
629 return boost::asio::buffer(*buffer);
630 }
631
632 template <typename B = Buffer>
633 typename std::enable_if<!boost::has_dereference<B>::value,
634 boost::asio::const_buffer>::type
635 data()
636 {
637 return boost::asio::buffer(buffer);
638 }
639
640 const std::string name;
641 boost::process::async_pipe impl;
642 Buffer buffer;
643};
644
645/**
646 * @brief Function transceives data with dbus directly.
647 *
648 * All BMC state properties will be retrieved before sending reset request.
649 */
650inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
651 const std::string& service, const std::string& name,
652 const std::string& imageUrl, const bool rw,
653 std::string&& userName, std::string&& password)
654{
655 using SecurePipe = Pipe<CredentialsProvider::SecureBuffer>;
656 constexpr const size_t secretLimit = 1024;
657
658 std::shared_ptr<SecurePipe> secretPipe;
Ed Tanous168e20c2021-12-13 14:39:53 -0800659 dbus::utility::DbusVariantType unixFd = -1;
Ed Tanous22db1722021-06-09 10:53:51 -0700660
661 if (!userName.empty() || !password.empty())
662 {
663 // Encapsulate in safe buffer
664 CredentialsProvider credentials(std::move(userName),
665 std::move(password));
666
667 // Payload must contain data + NULL delimiters
668 if (credentials.user().size() + credentials.password().size() + 2 >
669 secretLimit)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100670 {
Ed Tanous22db1722021-06-09 10:53:51 -0700671 BMCWEB_LOG_ERROR << "Credentials too long to handle";
672 messages::unrecognizedRequestBody(asyncResp->res);
673 return;
674 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100675
Ed Tanous22db1722021-06-09 10:53:51 -0700676 // Pack secret
677 auto secret = credentials.pack(
678 [](const auto& user, const auto& pass, auto& buff) {
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100679 std::copy(user.begin(), user.end(), std::back_inserter(buff));
680 buff.push_back('\0');
681 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
682 buff.push_back('\0');
683 });
684
Ed Tanous22db1722021-06-09 10:53:51 -0700685 // Open pipe
686 secretPipe = std::make_shared<SecurePipe>(
687 crow::connections::systemBus->get_io_context(), std::move(secret));
688 unixFd = secretPipe->fd();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100689
Ed Tanous22db1722021-06-09 10:53:51 -0700690 // Pass secret over pipe
691 secretPipe->asyncWrite(
692 [asyncResp](const boost::system::error_code& ec, std::size_t) {
693 if (ec)
694 {
695 BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
696 messages::internalError(asyncResp->res);
697 }
698 });
699 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100700
Ed Tanous22db1722021-06-09 10:53:51 -0700701 crow::connections::systemBus->async_method_call(
702 [asyncResp, secretPipe](const boost::system::error_code ec,
703 bool success) {
704 if (ec)
705 {
706 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
707 messages::internalError(asyncResp->res);
708 }
709 else if (!success)
710 {
711 BMCWEB_LOG_ERROR << "Service responded with error";
712 messages::generalError(asyncResp->res);
713 }
714 },
715 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
716 "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
717 unixFd);
718}
719
720/**
721 * @brief Function transceives data with dbus directly.
722 *
723 * All BMC state properties will be retrieved before sending reset request.
724 */
725inline void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
726 const std::string& service, const std::string& name,
727 bool legacy)
728{
729
730 // Legacy mount requires parameter with image
731 if (legacy)
732 {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100733 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700734 [asyncResp](const boost::system::error_code ec) {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100735 if (ec)
736 {
737 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700738
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100739 messages::internalError(asyncResp->res);
Ed Tanous22db1722021-06-09 10:53:51 -0700740 return;
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100741 }
742 },
743 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
Ed Tanous22db1722021-06-09 10:53:51 -0700744 "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200745 }
Ed Tanous22db1722021-06-09 10:53:51 -0700746 else // proxy
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200747 {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200748 crow::connections::systemBus->async_method_call(
Ed Tanous22db1722021-06-09 10:53:51 -0700749 [asyncResp](const boost::system::error_code ec) {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200750 if (ec)
751 {
Ed Tanous22db1722021-06-09 10:53:51 -0700752 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
753
zhanghch058d1b46d2021-04-01 11:18:24 +0800754 messages::internalError(asyncResp->res);
Ed Tanous22db1722021-06-09 10:53:51 -0700755 return;
756 }
757 },
758 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
759 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
760 }
761}
762
Ed Tanous98be3e32021-09-16 15:05:36 -0700763struct InsertMediaActionParams
764{
765 std::string imageUrl;
766 std::optional<std::string> userName;
767 std::optional<std::string> password;
768 std::optional<std::string> transferMethod;
769 std::optional<std::string> transferProtocolType;
770 std::optional<bool> writeProtected = true;
771 std::optional<bool> inserted;
772};
773
Ed Tanous22db1722021-06-09 10:53:51 -0700774inline void requestNBDVirtualMediaRoutes(App& app)
775{
George Liu0fda0f12021-11-16 10:06:17 +0800776 BMCWEB_ROUTE(
777 app,
778 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
Ed Tanoused398212021-06-09 17:05:54 -0700779 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -0700780 .methods(boost::beast::http::verb::post)(
781 [](const crow::Request& req,
782 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
783 const std::string& name, const std::string& resName) {
784 if (name != "bmc")
785 {
786 messages::resourceNotFound(asyncResp->res,
787 "VirtualMedia.Insert", resName);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200788
789 return;
790 }
Ed Tanous98be3e32021-09-16 15:05:36 -0700791 InsertMediaActionParams actionParams;
792
793 // Read obligatory parameters (url of
794 // image)
Willy Tu15ed6782021-12-14 11:03:16 -0800795 if (!json_util::readJsonAction(
Ed Tanous98be3e32021-09-16 15:05:36 -0700796 req, asyncResp->res, "Image", actionParams.imageUrl,
797 "WriteProtected", actionParams.writeProtected,
798 "UserName", actionParams.userName, "Password",
799 actionParams.password, "Inserted",
800 actionParams.inserted, "TransferMethod",
801 actionParams.transferMethod, "TransferProtocolType",
802 actionParams.transferProtocolType))
803 {
804 BMCWEB_LOG_DEBUG << "Image is not provided";
805 return;
806 }
807
808 bool paramsValid = validateParams(
809 asyncResp->res, actionParams.imageUrl,
810 actionParams.inserted, actionParams.transferMethod,
811 actionParams.transferProtocolType);
812
Ed Tanouse05aec52022-01-25 10:28:56 -0800813 if (!paramsValid)
Ed Tanous98be3e32021-09-16 15:05:36 -0700814 {
815 return;
816 }
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200817
818 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700819 [asyncResp, actionParams,
Ed Tanous22db1722021-06-09 10:53:51 -0700820 resName](const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800821 const dbus::utility::MapperGetObject&
822 getObjectType) mutable {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200823 if (ec)
824 {
Ed Tanous22db1722021-06-09 10:53:51 -0700825 BMCWEB_LOG_ERROR
826 << "ObjectMapper::GetObject call failed: "
827 << ec;
828 messages::internalError(asyncResp->res);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200829
830 return;
831 }
Ed Tanous22db1722021-06-09 10:53:51 -0700832 std::string service = getObjectType.begin()->first;
833 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200834
Ed Tanous22db1722021-06-09 10:53:51 -0700835 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700836 [service, resName, actionParams,
Ed Tanous22db1722021-06-09 10:53:51 -0700837 asyncResp](const boost::system::error_code ec,
Ed Tanous711ac7a2021-12-20 09:34:41 -0800838 dbus::utility::ManagedObjectType&
839 subtree) mutable {
Ed Tanous22db1722021-06-09 10:53:51 -0700840 if (ec)
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200841 {
Ed Tanous22db1722021-06-09 10:53:51 -0700842 BMCWEB_LOG_DEBUG << "DBUS response error";
843
844 return;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200845 }
846
Ed Tanous22db1722021-06-09 10:53:51 -0700847 for (const auto& object : subtree)
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200848 {
Ed Tanous22db1722021-06-09 10:53:51 -0700849 const std::string& path =
850 static_cast<const std::string&>(
851 object.first);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200852
Ed Tanous22db1722021-06-09 10:53:51 -0700853 std::size_t lastIndex = path.rfind('/');
854 if (lastIndex == std::string::npos)
855 {
856 continue;
857 }
858
859 lastIndex += 1;
860
861 if (path.substr(lastIndex) == resName)
862 {
863 lastIndex = path.rfind("Proxy");
864 if (lastIndex != std::string::npos)
865 {
866 // Not possible in proxy mode
867 BMCWEB_LOG_DEBUG
868 << "InsertMedia not "
869 "allowed in proxy mode";
870 messages::resourceNotFound(
871 asyncResp->res,
872 "VirtualMedia.InsertMedia",
873 resName);
874
875 return;
876 }
877
878 lastIndex = path.rfind("Legacy");
879 if (lastIndex == std::string::npos)
880 {
881 continue;
882 }
883
Ed Tanous22db1722021-06-09 10:53:51 -0700884 // manager is irrelevant for
885 // VirtualMedia dbus calls
Ed Tanous98be3e32021-09-16 15:05:36 -0700886 doMountVmLegacy(
887 asyncResp, service, resName,
888 actionParams.imageUrl,
889 !(*actionParams.writeProtected),
890 std::move(*actionParams.userName),
891 std::move(*actionParams.password));
Ed Tanous22db1722021-06-09 10:53:51 -0700892
893 return;
894 }
895 }
896 BMCWEB_LOG_DEBUG << "Parent item not found";
897 messages::resourceNotFound(
898 asyncResp->res, "VirtualMedia", resName);
899 },
900 service, "/xyz/openbmc_project/VirtualMedia",
901 "org.freedesktop.DBus.ObjectManager",
902 "GetManagedObjects");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200903 },
Ed Tanous22db1722021-06-09 10:53:51 -0700904 "xyz.openbmc_project.ObjectMapper",
905 "/xyz/openbmc_project/object_mapper",
906 "xyz.openbmc_project.ObjectMapper", "GetObject",
907 "/xyz/openbmc_project/VirtualMedia",
908 std::array<const char*, 0>());
909 });
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200910
George Liu0fda0f12021-11-16 10:06:17 +0800911 BMCWEB_ROUTE(
912 app,
913 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
Ed Tanoused398212021-06-09 17:05:54 -0700914 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -0700915 .methods(boost::beast::http::verb::post)(
Ed Tanous98be3e32021-09-16 15:05:36 -0700916 [](const crow::Request&,
Ed Tanous22db1722021-06-09 10:53:51 -0700917 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
918 const std::string& name, const std::string& resName) {
919 if (name != "bmc")
920 {
921 messages::resourceNotFound(asyncResp->res,
922 "VirtualMedia.Eject", resName);
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200923
Ed Tanous22db1722021-06-09 10:53:51 -0700924 return;
925 }
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200926
Ed Tanous22db1722021-06-09 10:53:51 -0700927 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -0800928 [asyncResp, resName](
929 const boost::system::error_code ec,
930 const dbus::utility::MapperGetObject& getObjectType) {
Ed Tanous22db1722021-06-09 10:53:51 -0700931 if (ec)
932 {
933 BMCWEB_LOG_ERROR
934 << "ObjectMapper::GetObject call failed: "
935 << ec;
936 messages::internalError(asyncResp->res);
937
938 return;
939 }
940 std::string service = getObjectType.begin()->first;
941 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
942
943 crow::connections::systemBus->async_method_call(
Ed Tanous98be3e32021-09-16 15:05:36 -0700944 [resName, service, asyncResp{asyncResp}](
Ed Tanous22db1722021-06-09 10:53:51 -0700945 const boost::system::error_code ec,
Ed Tanous711ac7a2021-12-20 09:34:41 -0800946 dbus::utility::ManagedObjectType& subtree) {
Ed Tanous22db1722021-06-09 10:53:51 -0700947 if (ec)
948 {
949 BMCWEB_LOG_DEBUG << "DBUS response error";
950
951 return;
952 }
953
954 for (const auto& object : subtree)
955 {
956 const std::string& path =
957 static_cast<const std::string&>(
958 object.first);
959
960 std::size_t lastIndex = path.rfind('/');
961 if (lastIndex == std::string::npos)
962 {
963 continue;
964 }
965
966 lastIndex += 1;
967
968 if (path.substr(lastIndex) == resName)
969 {
970 lastIndex = path.rfind("Proxy");
971 if (lastIndex != std::string::npos)
972 {
973 // Proxy mode
974 doVmAction(asyncResp, service,
975 resName, false);
976 }
977
978 lastIndex = path.rfind("Legacy");
979 if (lastIndex != std::string::npos)
980 {
981 // Legacy mode
982 doVmAction(asyncResp, service,
983 resName, true);
984 }
985
986 return;
987 }
988 }
989 BMCWEB_LOG_DEBUG << "Parent item not found";
990 messages::resourceNotFound(
991 asyncResp->res, "VirtualMedia", resName);
992 },
993 service, "/xyz/openbmc_project/VirtualMedia",
994 "org.freedesktop.DBus.ObjectManager",
995 "GetManagedObjects");
996 },
997 "xyz.openbmc_project.ObjectMapper",
998 "/xyz/openbmc_project/object_mapper",
999 "xyz.openbmc_project.ObjectMapper", "GetObject",
1000 "/xyz/openbmc_project/VirtualMedia",
1001 std::array<const char*, 0>());
1002 });
1003 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
Ed Tanoused398212021-06-09 17:05:54 -07001004 .privileges(redfish::privileges::getVirtualMediaCollection)
Ed Tanous22db1722021-06-09 10:53:51 -07001005 .methods(boost::beast::http::verb::get)(
1006 [](const crow::Request& /* req */,
1007 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1008 const std::string& name) {
1009 if (name != "bmc")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001010 {
Ed Tanous22db1722021-06-09 10:53:51 -07001011 messages::resourceNotFound(asyncResp->res, "VirtualMedia",
1012 name);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001013
1014 return;
1015 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001016
Ed Tanous22db1722021-06-09 10:53:51 -07001017 asyncResp->res.jsonValue["@odata.type"] =
1018 "#VirtualMediaCollection.VirtualMediaCollection";
1019 asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
1020 asyncResp->res.jsonValue["@odata.id"] =
1021 "/redfish/v1/Managers/" + name + "/VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001022
Ed Tanous22db1722021-06-09 10:53:51 -07001023 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001024 [asyncResp, name](
1025 const boost::system::error_code ec,
1026 const dbus::utility::MapperGetObject& getObjectType) {
Ed Tanous22db1722021-06-09 10:53:51 -07001027 if (ec)
1028 {
1029 BMCWEB_LOG_ERROR
1030 << "ObjectMapper::GetObject call failed: "
1031 << ec;
1032 messages::internalError(asyncResp->res);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001033
Ed Tanous22db1722021-06-09 10:53:51 -07001034 return;
1035 }
1036 std::string service = getObjectType.begin()->first;
1037 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001038
Ed Tanous22db1722021-06-09 10:53:51 -07001039 getVmResourceList(asyncResp, service, name);
1040 },
1041 "xyz.openbmc_project.ObjectMapper",
1042 "/xyz/openbmc_project/object_mapper",
1043 "xyz.openbmc_project.ObjectMapper", "GetObject",
1044 "/xyz/openbmc_project/VirtualMedia",
1045 std::array<const char*, 0>());
1046 });
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001047
Ed Tanous22db1722021-06-09 10:53:51 -07001048 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001049 .privileges(redfish::privileges::getVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -07001050 .methods(boost::beast::http::verb::get)(
1051 [](const crow::Request& /* req */,
1052 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1053 const std::string& name, const std::string& resName) {
1054 if (name != "bmc")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001055 {
Ed Tanous22db1722021-06-09 10:53:51 -07001056 messages::resourceNotFound(asyncResp->res, "VirtualMedia",
1057 resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001058
1059 return;
1060 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001061
Ed Tanous22db1722021-06-09 10:53:51 -07001062 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001063 [asyncResp, name, resName](
1064 const boost::system::error_code ec,
1065 const dbus::utility::MapperGetObject& getObjectType) {
Ed Tanous22db1722021-06-09 10:53:51 -07001066 if (ec)
1067 {
1068 BMCWEB_LOG_ERROR
1069 << "ObjectMapper::GetObject call failed: "
1070 << ec;
1071 messages::internalError(asyncResp->res);
1072
1073 return;
1074 }
1075 std::string service = getObjectType.begin()->first;
1076 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1077
1078 getVmData(asyncResp, service, name, resName);
1079 },
1080 "xyz.openbmc_project.ObjectMapper",
1081 "/xyz/openbmc_project/object_mapper",
1082 "xyz.openbmc_project.ObjectMapper", "GetObject",
1083 "/xyz/openbmc_project/VirtualMedia",
1084 std::array<const char*, 0>());
1085 });
1086}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001087
1088} // namespace redfish