blob: 73a9855aa8d72534a7f5f492cda308a01e95c51b [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 Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "account_service.hpp"
19#include "app.hpp"
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +020020#include "async_resp.hpp"
George Liu2b731192023-01-11 16:27:13 +080021#include "dbus_utility.hpp"
Ed Tanous739b87e2023-02-24 13:13:33 -080022#include "generated/enums/virtual_media.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080023#include "query.hpp"
24#include "registries/privilege_registry.hpp"
25#include "utils/json_utils.hpp"
26
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +010027#include <boost/process/async_pipe.hpp>
Anna Platash9e319cf2020-11-17 10:18:31 +010028#include <boost/url/url_view.hpp>
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020029
George Liu2b731192023-01-11 16:27:13 +080030#include <array>
31#include <string_view>
32
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020033namespace redfish
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020034{
Ed Tanous365a73f2023-02-24 12:16:49 -080035
36enum class VmMode
37{
38 Invalid,
39 Legacy,
40 Proxy
41};
42
43inline VmMode
44 parseObjectPathAndGetMode(const sdbusplus::message::object_path& itemPath,
45 const std::string& resName)
46{
47 std::string thisPath = itemPath.filename();
48 BMCWEB_LOG_DEBUG << "Filename: " << itemPath.str
49 << ", ThisPath: " << thisPath;
50
51 if (thisPath.empty())
52 {
53 return VmMode::Invalid;
54 }
55
56 if (thisPath != resName)
57 {
58 return VmMode::Invalid;
59 }
60
61 auto mode = itemPath.parent_path();
62 auto type = mode.parent_path();
63
64 if (mode.filename().empty() || type.filename().empty())
65 {
66 return VmMode::Invalid;
67 }
68
69 if (type.filename() != "VirtualMedia")
70 {
71 return VmMode::Invalid;
72 }
73 std::string modeStr = mode.filename();
74 if (modeStr == "Legacy")
75 {
76 return VmMode::Legacy;
77 }
78 if (modeStr == "Proxy")
79 {
80 return VmMode::Proxy;
81 }
82 return VmMode::Invalid;
83}
84
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +020085using CheckItemHandler =
86 std::function<void(const std::string& service, const std::string& resName,
87 const std::shared_ptr<bmcweb::AsyncResp>&,
George Liu70cbdf52023-03-04 12:07:25 +080088 const std::pair<sdbusplus::message::object_path,
89 dbus::utility::DBusInteracesMap>&)>;
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +020090
91inline void findAndParseObject(const std::string& service,
92 const std::string& resName,
93 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
94 CheckItemHandler&& handler)
95{
96 crow::connections::systemBus->async_method_call(
97 [service, resName, aResp,
Lakshmi Yadlapati746c5b82023-03-06 16:07:28 -060098 handler](const boost::system::error_code& ec,
George Liu70cbdf52023-03-04 12:07:25 +080099 const dbus::utility::ManagedObjectType& subtree) {
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200100 if (ec)
101 {
102 BMCWEB_LOG_DEBUG << "DBUS response error";
103
104 return;
105 }
106
George Liu70cbdf52023-03-04 12:07:25 +0800107 for (const auto& item : subtree)
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200108 {
109 VmMode mode = parseObjectPathAndGetMode(item.first, resName);
110 if (mode != VmMode::Invalid)
111 {
112 handler(service, resName, aResp, item);
113 return;
114 }
115 }
116
117 BMCWEB_LOG_DEBUG << "Parent item not found";
118 aResp->res.result(boost::beast::http::status::not_found);
119 },
120 service, "/xyz/openbmc_project/VirtualMedia",
121 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
122}
123
Anna Platash9e319cf2020-11-17 10:18:31 +0100124/**
125 * @brief Function extracts transfer protocol name from URI.
126 */
Ed Tanous67df0732021-10-26 11:23:56 -0700127inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
128{
129 boost::urls::result<boost::urls::url_view> url =
Ed Tanous079360a2022-06-29 10:05:19 -0700130 boost::urls::parse_uri(imageUri);
Ed Tanous67df0732021-10-26 11:23:56 -0700131 if (!url)
132 {
133 return "None";
134 }
Ed Tanous079360a2022-06-29 10:05:19 -0700135 std::string_view scheme = url->scheme();
Ed Tanous67df0732021-10-26 11:23:56 -0700136 if (scheme == "smb")
137 {
138 return "CIFS";
139 }
140 if (scheme == "https")
141 {
142 return "HTTPS";
143 }
144
145 return "None";
146}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200147
148/**
149 * @brief Read all known properties from VM object interfaces
150 */
Ed Tanous22db1722021-06-09 10:53:51 -0700151inline void
Ed Tanous8a592812022-06-04 09:06:59 -0700152 vmParseInterfaceObject(const dbus::utility::DBusInteracesMap& interfaces,
zhanghch058d1b46d2021-04-01 11:18:24 +0800153 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200154{
Ed Tanous8a592812022-06-04 09:06:59 -0700155 for (const auto& [interface, values] : interfaces)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200156 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800157 if (interface == "xyz.openbmc_project.VirtualMedia.MountPoint")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200158 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800159 for (const auto& [property, value] : values)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200160 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800161 if (property == "EndpointId")
162 {
163 const std::string* endpointIdValue =
164 std::get_if<std::string>(&value);
165 if (endpointIdValue == nullptr)
166 {
167 continue;
168 }
169 if (!endpointIdValue->empty())
170 {
171 // Proxy mode
172 aResp->res
173 .jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
174 *endpointIdValue;
175 aResp->res.jsonValue["TransferProtocolType"] = "OEM";
176 }
177 }
178 if (property == "ImageURL")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200179 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100180 const std::string* imageUrlValue =
Ed Tanous711ac7a2021-12-20 09:34:41 -0800181 std::get_if<std::string>(&value);
Ed Tanous26f69762022-01-25 09:49:11 -0800182 if (imageUrlValue != nullptr && !imageUrlValue->empty())
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100183 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100184 std::filesystem::path filePath = *imageUrlValue;
185 if (!filePath.has_filename())
186 {
187 // this will handle https share, which not
188 // necessarily has to have filename given.
189 aResp->res.jsonValue["ImageName"] = "";
190 }
191 else
192 {
193 aResp->res.jsonValue["ImageName"] =
194 filePath.filename();
195 }
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100196
Anna Platash9e319cf2020-11-17 10:18:31 +0100197 aResp->res.jsonValue["Image"] = *imageUrlValue;
Anna Platash9e319cf2020-11-17 10:18:31 +0100198 aResp->res.jsonValue["TransferProtocolType"] =
199 getTransferProtocolTypeFromUri(*imageUrlValue);
200
Ed Tanous739b87e2023-02-24 13:13:33 -0800201 aResp->res.jsonValue["ConnectedVia"] =
202 virtual_media::ConnectedVia::URI;
Anna Platash9e319cf2020-11-17 10:18:31 +0100203 }
204 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800205 if (property == "WriteProtected")
Anna Platash9e319cf2020-11-17 10:18:31 +0100206 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800207 const bool* writeProtectedValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800208 if (writeProtectedValue != nullptr)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200209 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100210 aResp->res.jsonValue["WriteProtected"] =
211 *writeProtectedValue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200212 }
213 }
214 }
215 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800216 if (interface == "xyz.openbmc_project.VirtualMedia.Process")
217 {
218 for (const auto& [property, value] : values)
219 {
220 if (property == "Active")
221 {
222 const bool* activeValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800223 if (activeValue == nullptr)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800224 {
225 BMCWEB_LOG_DEBUG << "Value Active not found";
226 return;
227 }
228 aResp->res.jsonValue["Inserted"] = *activeValue;
229
Ed Tanouse05aec52022-01-25 10:28:56 -0800230 if (*activeValue)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800231 {
Ed Tanous739b87e2023-02-24 13:13:33 -0800232 aResp->res.jsonValue["ConnectedVia"] =
233 virtual_media::ConnectedVia::Applet;
Ed Tanous711ac7a2021-12-20 09:34:41 -0800234 }
235 }
236 }
237 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200238 }
239}
240
241/**
242 * @brief Fill template for Virtual Media Item.
243 */
Ed Tanous22db1722021-06-09 10:53:51 -0700244inline nlohmann::json vmItemTemplate(const std::string& name,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500245 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200246{
247 nlohmann::json item;
Ed Tanousfdb20342022-06-03 09:56:52 -0700248 item["@odata.id"] = crow::utility::urlFromPieces(
249 "redfish", "v1", "Managers", name, "VirtualMedia", resName);
Ed Tanous22db1722021-06-09 10:53:51 -0700250
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100251 item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200252 item["Name"] = "Virtual Removable Media";
253 item["Id"] = resName;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200254 item["WriteProtected"] = true;
Ed Tanous739b87e2023-02-24 13:13:33 -0800255 item["ConnectedVia"] = virtual_media::ConnectedVia::NotConnected;
Ed Tanous613dabe2022-07-09 11:17:36 -0700256 item["MediaTypes"] = nlohmann::json::array_t({"CD", "USBStick"});
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200257 item["TransferMethod"] = "Stream";
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100258 item["Oem"]["OpenBMC"]["@odata.type"] =
259 "#OemVirtualMedia.v1_0_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200260
261 return item;
262}
263
264/**
265 * @brief Fills collection data
266 */
Ed Tanous22db1722021-06-09 10:53:51 -0700267inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500268 const std::string& service,
269 const std::string& name)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200270{
271 BMCWEB_LOG_DEBUG << "Get available Virtual Media resources.";
272 crow::connections::systemBus->async_method_call(
Ed Tanous02cad962022-06-30 16:50:15 -0700273 [name, aResp{std::move(aResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800274 const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700275 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700276 if (ec)
277 {
278 BMCWEB_LOG_DEBUG << "DBUS response error";
279 return;
280 }
281 nlohmann::json& members = aResp->res.jsonValue["Members"];
282 members = nlohmann::json::array();
283
284 for (const auto& object : subtree)
285 {
286 nlohmann::json item;
287 std::string path = object.first.filename();
288 if (path.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200289 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700290 continue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200291 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200292
Ed Tanousfdb20342022-06-03 09:56:52 -0700293 item["@odata.id"] = crow::utility::urlFromPieces(
294 "redfish", "v1", "Managers", name, "VirtualMedia", path);
Ed Tanous002d39b2022-05-31 08:59:27 -0700295 members.emplace_back(std::move(item));
296 }
297 aResp->res.jsonValue["Members@odata.count"] = members.size();
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200298 },
299 service, "/xyz/openbmc_project/VirtualMedia",
300 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
301}
302
George Liu70cbdf52023-03-04 12:07:25 +0800303inline void
304 afterGetVmData(const std::string& name, const std::string& /*service*/,
305 const std::string& resName,
306 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
307 const std::pair<sdbusplus::message::object_path,
308 dbus::utility::DBusInteracesMap>& item)
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200309{
310 VmMode mode = parseObjectPathAndGetMode(item.first, resName);
311 if (mode == VmMode::Invalid)
312 {
313 return;
314 }
315
316 asyncResp->res.jsonValue = vmItemTemplate(name, resName);
317
318 // Check if dbus path is Legacy type
319 if (mode == VmMode::Legacy)
320 {
321 asyncResp->res
322 .jsonValue["Actions"]["#VirtualMedia.InsertMedia"]["target"] =
323 crow::utility::urlFromPieces("redfish", "v1", "Managers", name,
324 "VirtualMedia", resName, "Actions",
325 "VirtualMedia.InsertMedia");
326 }
327
328 vmParseInterfaceObject(item.second, asyncResp);
329
330 asyncResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"]["target"] =
331 crow::utility::urlFromPieces("redfish", "v1", "Managers", name,
332 "VirtualMedia", resName, "Actions",
333 "VirtualMedia.EjectMedia");
334}
335
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200336/**
337 * @brief Fills data for specific resource
338 */
Ed Tanous22db1722021-06-09 10:53:51 -0700339inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500340 const std::string& service, const std::string& name,
341 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200342{
343 BMCWEB_LOG_DEBUG << "Get Virtual Media resource data.";
344
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200345 findAndParseObject(service, resName, aResp,
George Liu70cbdf52023-03-04 12:07:25 +0800346 std::bind_front(afterGetVmData, name));
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200347}
348
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200349/**
Ed Tanous22db1722021-06-09 10:53:51 -0700350 * @brief Transfer protocols supported for InsertMedia action.
351 *
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200352 */
Ed Tanous22db1722021-06-09 10:53:51 -0700353enum class TransferProtocol
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200354{
Ed Tanous22db1722021-06-09 10:53:51 -0700355 https,
356 smb,
357 invalid
358};
359
360/**
361 * @brief Function extracts transfer protocol type from URI.
362 *
363 */
Ed Tanous67df0732021-10-26 11:23:56 -0700364inline std::optional<TransferProtocol>
Ed Tanousace85d62021-10-26 12:45:59 -0700365 getTransferProtocolFromUri(const boost::urls::url_view& imageUri)
Ed Tanous67df0732021-10-26 11:23:56 -0700366{
Ed Tanous079360a2022-06-29 10:05:19 -0700367 std::string_view scheme = imageUri.scheme();
Ed Tanous67df0732021-10-26 11:23:56 -0700368 if (scheme == "smb")
369 {
370 return TransferProtocol::smb;
371 }
372 if (scheme == "https")
373 {
374 return TransferProtocol::https;
375 }
376 if (!scheme.empty())
377 {
378 return TransferProtocol::invalid;
379 }
380
381 return {};
382}
Ed Tanous22db1722021-06-09 10:53:51 -0700383
384/**
385 * @brief Function convert transfer protocol from string param.
386 *
387 */
388inline std::optional<TransferProtocol> getTransferProtocolFromParam(
389 const std::optional<std::string>& transferProtocolType)
390{
391 if (transferProtocolType == std::nullopt)
Agata Olenderc6f4e012020-03-11 15:19:07 +0100392 {
Ed Tanous22db1722021-06-09 10:53:51 -0700393 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100394 }
395
Ed Tanous22db1722021-06-09 10:53:51 -0700396 if (*transferProtocolType == "CIFS")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200397 {
Ed Tanous22db1722021-06-09 10:53:51 -0700398 return TransferProtocol::smb;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200399 }
400
Ed Tanous22db1722021-06-09 10:53:51 -0700401 if (*transferProtocolType == "HTTPS")
402 {
403 return TransferProtocol::https;
404 }
405
406 return TransferProtocol::invalid;
407}
408
409/**
410 * @brief Function extends URI with transfer protocol type.
411 *
412 */
413inline std::string
414 getUriWithTransferProtocol(const std::string& imageUri,
415 const TransferProtocol& transferProtocol)
416{
417 if (transferProtocol == TransferProtocol::smb)
418 {
419 return "smb://" + imageUri;
420 }
421
422 if (transferProtocol == TransferProtocol::https)
423 {
424 return "https://" + imageUri;
425 }
426
427 return imageUri;
428}
429
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200430struct InsertMediaActionParams
431{
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200432 std::optional<std::string> imageUrl;
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200433 std::optional<std::string> userName;
434 std::optional<std::string> password;
435 std::optional<std::string> transferMethod;
436 std::optional<std::string> transferProtocolType;
437 std::optional<bool> writeProtected = true;
438 std::optional<bool> inserted;
439};
440
Ed Tanous22db1722021-06-09 10:53:51 -0700441template <typename T>
442static void secureCleanup(T& value)
443{
Ed Tanous4ecc6182022-01-07 09:36:26 -0800444 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
Ed Tanous22db1722021-06-09 10:53:51 -0700445 auto raw = const_cast<typename T::value_type*>(value.data());
446 explicit_bzero(raw, value.size() * sizeof(*raw));
447}
448
449class Credentials
450{
451 public:
452 Credentials(std::string&& user, std::string&& password) :
453 userBuf(std::move(user)), passBuf(std::move(password))
454 {}
455
456 ~Credentials()
457 {
458 secureCleanup(userBuf);
459 secureCleanup(passBuf);
460 }
461
462 const std::string& user()
463 {
464 return userBuf;
465 }
466
467 const std::string& password()
468 {
469 return passBuf;
470 }
471
472 Credentials() = delete;
473 Credentials(const Credentials&) = delete;
474 Credentials& operator=(const Credentials&) = delete;
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800475 Credentials(Credentials&&) = delete;
476 Credentials& operator=(Credentials&&) = delete;
Ed Tanous22db1722021-06-09 10:53:51 -0700477
478 private:
479 std::string userBuf;
480 std::string passBuf;
481};
482
483class CredentialsProvider
484{
485 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500486 template <typename T>
Ed Tanous22db1722021-06-09 10:53:51 -0700487 struct Deleter
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100488 {
Ed Tanous22db1722021-06-09 10:53:51 -0700489 void operator()(T* buff) const
490 {
491 if (buff)
492 {
493 secureCleanup(*buff);
494 delete buff;
495 }
496 }
497 };
498
499 using Buffer = std::vector<char>;
500 using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
501 // Using explicit definition instead of std::function to avoid implicit
502 // conversions eg. stack copy instead of reference
503 using FormatterFunc = void(const std::string& username,
504 const std::string& password, Buffer& dest);
505
506 CredentialsProvider(std::string&& user, std::string&& password) :
507 credentials(std::move(user), std::move(password))
508 {}
509
510 const std::string& user()
511 {
512 return credentials.user();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100513 }
514
Ed Tanous22db1722021-06-09 10:53:51 -0700515 const std::string& password()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100516 {
Ed Tanous22db1722021-06-09 10:53:51 -0700517 return credentials.password();
518 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100519
Ed Tanous1917ee92022-06-30 22:30:50 -0700520 SecureBuffer pack(FormatterFunc* formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100521 {
Ed Tanous22db1722021-06-09 10:53:51 -0700522 SecureBuffer packed{new Buffer{}};
Ed Tanouse662eae2022-01-25 10:39:19 -0800523 if (formatter != nullptr)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100524 {
Ed Tanous22db1722021-06-09 10:53:51 -0700525 formatter(credentials.user(), credentials.password(), *packed);
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100526 }
527
Ed Tanous22db1722021-06-09 10:53:51 -0700528 return packed;
529 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100530
Ed Tanous22db1722021-06-09 10:53:51 -0700531 private:
532 Credentials credentials;
533};
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100534
Ed Tanous22db1722021-06-09 10:53:51 -0700535// Wrapper for boost::async_pipe ensuring proper pipe cleanup
Ed Tanous0a483062022-07-11 10:18:50 -0700536class SecurePipe
Ed Tanous22db1722021-06-09 10:53:51 -0700537{
538 public:
539 using unix_fd = sdbusplus::message::unix_fd;
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100540
Ed Tanous0a483062022-07-11 10:18:50 -0700541 SecurePipe(boost::asio::io_context& io,
542 CredentialsProvider::SecureBuffer&& bufferIn) :
543 impl(io),
544 buffer{std::move(bufferIn)}
Ed Tanous22db1722021-06-09 10:53:51 -0700545 {}
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100546
Ed Tanous0a483062022-07-11 10:18:50 -0700547 ~SecurePipe()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100548 {
Ed Tanous22db1722021-06-09 10:53:51 -0700549 // Named pipe needs to be explicitly removed
550 impl.close();
551 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100552
Ed Tanous0a483062022-07-11 10:18:50 -0700553 SecurePipe(const SecurePipe&) = delete;
554 SecurePipe(SecurePipe&&) = delete;
555 SecurePipe& operator=(const SecurePipe&) = delete;
556 SecurePipe& operator=(SecurePipe&&) = delete;
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800557
Ed Tanous0a483062022-07-11 10:18:50 -0700558 unix_fd fd() const
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200559 {
Ed Tanous22db1722021-06-09 10:53:51 -0700560 return unix_fd{impl.native_source()};
561 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100562
Ed Tanous22db1722021-06-09 10:53:51 -0700563 template <typename WriteHandler>
564 void asyncWrite(WriteHandler&& handler)
565 {
Ed Tanous0a483062022-07-11 10:18:50 -0700566 impl.async_write_some(boost::asio::buffer(*buffer),
567 std::forward<WriteHandler>(handler));
Ed Tanous22db1722021-06-09 10:53:51 -0700568 }
569
570 const std::string name;
571 boost::process::async_pipe impl;
Ed Tanous0a483062022-07-11 10:18:50 -0700572 CredentialsProvider::SecureBuffer buffer;
Ed Tanous22db1722021-06-09 10:53:51 -0700573};
574
575/**
576 * @brief Function transceives data with dbus directly.
577 *
578 * All BMC state properties will be retrieved before sending reset request.
579 */
580inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
581 const std::string& service, const std::string& name,
582 const std::string& imageUrl, const bool rw,
583 std::string&& userName, std::string&& password)
584{
Ed Tanous22db1722021-06-09 10:53:51 -0700585 constexpr const size_t secretLimit = 1024;
586
587 std::shared_ptr<SecurePipe> secretPipe;
Ed Tanous168e20c2021-12-13 14:39:53 -0800588 dbus::utility::DbusVariantType unixFd = -1;
Ed Tanous22db1722021-06-09 10:53:51 -0700589
590 if (!userName.empty() || !password.empty())
591 {
592 // Encapsulate in safe buffer
593 CredentialsProvider credentials(std::move(userName),
594 std::move(password));
595
596 // Payload must contain data + NULL delimiters
597 if (credentials.user().size() + credentials.password().size() + 2 >
598 secretLimit)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100599 {
Ed Tanous22db1722021-06-09 10:53:51 -0700600 BMCWEB_LOG_ERROR << "Credentials too long to handle";
601 messages::unrecognizedRequestBody(asyncResp->res);
602 return;
603 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100604
Ed Tanous22db1722021-06-09 10:53:51 -0700605 // Pack secret
606 auto secret = credentials.pack(
607 [](const auto& user, const auto& pass, auto& buff) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700608 std::copy(user.begin(), user.end(), std::back_inserter(buff));
609 buff.push_back('\0');
610 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
611 buff.push_back('\0');
612 });
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100613
Ed Tanous22db1722021-06-09 10:53:51 -0700614 // Open pipe
615 secretPipe = std::make_shared<SecurePipe>(
616 crow::connections::systemBus->get_io_context(), std::move(secret));
617 unixFd = secretPipe->fd();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100618
Ed Tanous22db1722021-06-09 10:53:51 -0700619 // Pass secret over pipe
620 secretPipe->asyncWrite(
621 [asyncResp](const boost::system::error_code& ec, std::size_t) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700622 if (ec)
623 {
624 BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
625 messages::internalError(asyncResp->res);
626 }
627 });
Ed Tanous22db1722021-06-09 10:53:51 -0700628 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100629
Ed Tanous22db1722021-06-09 10:53:51 -0700630 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800631 [asyncResp, secretPipe](const boost::system::error_code& ec,
Ed Tanous22db1722021-06-09 10:53:51 -0700632 bool success) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700633 if (ec)
634 {
635 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
636 messages::internalError(asyncResp->res);
637 }
638 else if (!success)
639 {
640 BMCWEB_LOG_ERROR << "Service responded with error";
641 messages::generalError(asyncResp->res);
642 }
Ed Tanous22db1722021-06-09 10:53:51 -0700643 },
644 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
645 "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
646 unixFd);
647}
648
649/**
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200650 * @brief Function validate parameters of insert media request.
651 *
652 */
653inline void validateParams(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
654 const std::string& service,
655 const std::string& resName,
656 InsertMediaActionParams& actionParams)
657{
658 BMCWEB_LOG_DEBUG << "Validation started";
659 // required param imageUrl must not be empty
660 if (!actionParams.imageUrl)
661 {
662 BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
663
664 messages::propertyValueFormatError(asyncResp->res, "<empty>", "Image");
665
666 return;
667 }
668
669 // optional param inserted must be true
670 if ((actionParams.inserted != std::nullopt) && !*actionParams.inserted)
671 {
672 BMCWEB_LOG_ERROR
673 << "Request action optional parameter Inserted must be true.";
674
675 messages::actionParameterNotSupported(asyncResp->res, "Inserted",
676 "InsertMedia");
677
678 return;
679 }
680
681 // optional param transferMethod must be stream
682 if ((actionParams.transferMethod != std::nullopt) &&
683 (*actionParams.transferMethod != "Stream"))
684 {
685 BMCWEB_LOG_ERROR << "Request action optional parameter "
686 "TransferMethod must be Stream.";
687
688 messages::actionParameterNotSupported(asyncResp->res, "TransferMethod",
689 "InsertMedia");
690
691 return;
692 }
693 boost::urls::result<boost::urls::url_view> url =
694 boost::urls::parse_uri(*actionParams.imageUrl);
695 if (!url)
696 {
697 messages::actionParameterValueFormatError(
698 asyncResp->res, *actionParams.imageUrl, "Image", "InsertMedia");
699 return;
700 }
701 std::optional<TransferProtocol> uriTransferProtocolType =
702 getTransferProtocolFromUri(*url);
703
704 std::optional<TransferProtocol> paramTransferProtocolType =
705 getTransferProtocolFromParam(actionParams.transferProtocolType);
706
707 // ImageUrl does not contain valid protocol type
708 if (*uriTransferProtocolType == TransferProtocol::invalid)
709 {
710 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
711 "contain specified protocol type from list: "
712 "(smb, https).";
713
714 messages::resourceAtUriInUnknownFormat(asyncResp->res, *url);
715
716 return;
717 }
718
719 // transferProtocolType should contain value from list
720 if (*paramTransferProtocolType == TransferProtocol::invalid)
721 {
722 BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
723 "must be provided with value from list: "
724 "(CIFS, HTTPS).";
725
726 messages::propertyValueNotInList(asyncResp->res,
727 *actionParams.transferProtocolType,
728 "TransferProtocolType");
729 return;
730 }
731
732 // valid transfer protocol not provided either with URI nor param
733 if ((uriTransferProtocolType == std::nullopt) &&
734 (paramTransferProtocolType == std::nullopt))
735 {
736 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
737 "contain specified protocol type or param "
738 "TransferProtocolType must be provided.";
739
740 messages::resourceAtUriInUnknownFormat(asyncResp->res, *url);
741
742 return;
743 }
744
745 // valid transfer protocol provided both with URI and param
746 if ((paramTransferProtocolType != std::nullopt) &&
747 (uriTransferProtocolType != std::nullopt))
748 {
749 // check if protocol is the same for URI and param
750 if (*paramTransferProtocolType != *uriTransferProtocolType)
751 {
752 BMCWEB_LOG_ERROR << "Request action parameter "
753 "TransferProtocolType must contain the "
754 "same protocol type as protocol type "
755 "provided with param imageUrl.";
756
757 messages::actionParameterValueTypeError(
758 asyncResp->res, *actionParams.transferProtocolType,
759 "TransferProtocolType", "InsertMedia");
760
761 return;
762 }
763 }
764
765 // validation passed, add protocol to URI if needed
766 if (uriTransferProtocolType == std::nullopt)
767 {
768 actionParams.imageUrl = getUriWithTransferProtocol(
769 *actionParams.imageUrl, *paramTransferProtocolType);
770 }
771
772 doMountVmLegacy(asyncResp, service, resName, *actionParams.imageUrl,
773 !(*actionParams.writeProtected),
774 std::move(*actionParams.userName),
775 std::move(*actionParams.password));
776}
777
778/**
Ed Tanous22db1722021-06-09 10:53:51 -0700779 * @brief Function transceives data with dbus directly.
780 *
781 * All BMC state properties will be retrieved before sending reset request.
782 */
Ed Tanous24e740a2023-02-24 12:08:58 -0800783inline void doEjectAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
784 const std::string& service, const std::string& name,
785 bool legacy)
Ed Tanous22db1722021-06-09 10:53:51 -0700786{
787
788 // Legacy mount requires parameter with image
789 if (legacy)
790 {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100791 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800792 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700793 if (ec)
794 {
795 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700796
Ed Tanous002d39b2022-05-31 08:59:27 -0700797 messages::internalError(asyncResp->res);
798 return;
799 }
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100800 },
801 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
Ed Tanous22db1722021-06-09 10:53:51 -0700802 "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200803 }
Ed Tanous22db1722021-06-09 10:53:51 -0700804 else // proxy
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200805 {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200806 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800807 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700808 if (ec)
809 {
810 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700811
Ed Tanous002d39b2022-05-31 08:59:27 -0700812 messages::internalError(asyncResp->res);
813 return;
814 }
Ed Tanous22db1722021-06-09 10:53:51 -0700815 },
816 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
817 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
818 }
819}
820
Ed Tanous96825be2022-06-03 09:43:38 -0700821inline void handleManagersVirtualMediaActionInsertPost(
822 crow::App& app, const crow::Request& req,
823 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
824 const std::string& name, const std::string& resName)
825{
826 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
827 {
828 return;
829 }
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200830
831 constexpr std::string_view action = "VirtualMedia.InsertMedia";
Ed Tanous96825be2022-06-03 09:43:38 -0700832 if (name != "bmc")
833 {
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200834 messages::resourceNotFound(asyncResp->res, action, resName);
Ed Tanous96825be2022-06-03 09:43:38 -0700835
836 return;
837 }
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200838 InsertMediaActionParams actionParams;
Ed Tanous96825be2022-06-03 09:43:38 -0700839
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200840 // Read obligatory parameters (url of image)
Ed Tanous96825be2022-06-03 09:43:38 -0700841 if (!json_util::readJsonAction(
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200842 req, asyncResp->res, "Image", actionParams.imageUrl,
843 "WriteProtected", actionParams.writeProtected, "UserName",
844 actionParams.userName, "Password", actionParams.password,
845 "Inserted", actionParams.inserted, "TransferMethod",
846 actionParams.transferMethod, "TransferProtocolType",
847 actionParams.transferProtocolType))
Ed Tanous96825be2022-06-03 09:43:38 -0700848 {
849 return;
850 }
851
George Liu2b731192023-01-11 16:27:13 +0800852 dbus::utility::getDbusObject(
853 "/xyz/openbmc_project/VirtualMedia", {},
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200854 [asyncResp, action, actionParams,
George Liu2b731192023-01-11 16:27:13 +0800855 resName](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -0700856 const dbus::utility::MapperGetObject& getObjectType) mutable {
857 if (ec)
858 {
859 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200860 messages::resourceNotFound(asyncResp->res, action, resName);
Ed Tanous96825be2022-06-03 09:43:38 -0700861
862 return;
863 }
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200864
Ed Tanous96825be2022-06-03 09:43:38 -0700865 std::string service = getObjectType.begin()->first;
866 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
867
868 crow::connections::systemBus->async_method_call(
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200869 [service, resName, action, actionParams,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800870 asyncResp](const boost::system::error_code& ec2,
Ed Tanous96825be2022-06-03 09:43:38 -0700871 dbus::utility::ManagedObjectType& subtree) mutable {
Ed Tanous8a592812022-06-04 09:06:59 -0700872 if (ec2)
Ed Tanous96825be2022-06-03 09:43:38 -0700873 {
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200874 // Not possible in proxy mode
875 BMCWEB_LOG_DEBUG << "InsertMedia not "
876 "allowed in proxy mode";
877 messages::resourceNotFound(asyncResp->res, action, resName);
Ed Tanous96825be2022-06-03 09:43:38 -0700878
879 return;
880 }
Ed Tanous96825be2022-06-03 09:43:38 -0700881 for (const auto& object : subtree)
882 {
Ed Tanous365a73f2023-02-24 12:16:49 -0800883 VmMode mode = parseObjectPathAndGetMode(object.first, resName);
884 if (mode == VmMode::Proxy)
Ed Tanous96825be2022-06-03 09:43:38 -0700885 {
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200886 validateParams(asyncResp, service, resName, actionParams);
Ed Tanous96825be2022-06-03 09:43:38 -0700887
888 return;
889 }
890 }
891 BMCWEB_LOG_DEBUG << "Parent item not found";
892 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
893 },
894 service, "/xyz/openbmc_project/VirtualMedia",
895 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
George Liu2b731192023-01-11 16:27:13 +0800896 });
Ed Tanous96825be2022-06-03 09:43:38 -0700897}
898
899inline void handleManagersVirtualMediaActionEject(
900 crow::App& app, const crow::Request& req,
901 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
902 const std::string& managerName, const std::string& resName)
903{
904 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
905 {
906 return;
907 }
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200908
909 constexpr std::string_view action = "VirtualMedia.EjectMedia";
Ed Tanous96825be2022-06-03 09:43:38 -0700910 if (managerName != "bmc")
911 {
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200912 messages::resourceNotFound(asyncResp->res, action, resName);
Ed Tanous96825be2022-06-03 09:43:38 -0700913
914 return;
915 }
916
George Liu2b731192023-01-11 16:27:13 +0800917 dbus::utility::getDbusObject(
918 "/xyz/openbmc_project/VirtualMedia", {},
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200919 [asyncResp, action,
George Liu2b731192023-01-11 16:27:13 +0800920 resName](const boost::system::error_code& ec2,
Ed Tanous96825be2022-06-03 09:43:38 -0700921 const dbus::utility::MapperGetObject& getObjectType) {
Ed Tanous8a592812022-06-04 09:06:59 -0700922 if (ec2)
Ed Tanous96825be2022-06-03 09:43:38 -0700923 {
Ed Tanous8a592812022-06-04 09:06:59 -0700924 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec2;
Ed Tanous96825be2022-06-03 09:43:38 -0700925 messages::internalError(asyncResp->res);
926
927 return;
928 }
929 std::string service = getObjectType.begin()->first;
930 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
931
932 crow::connections::systemBus->async_method_call(
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200933 [resName, service, action,
934 asyncResp](const boost::system::error_code& ec,
935 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous96825be2022-06-03 09:43:38 -0700936 if (ec)
937 {
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200938 BMCWEB_LOG_ERROR << "ObjectMapper : No Service found";
939 messages::resourceNotFound(asyncResp->res, action, resName);
Ed Tanous96825be2022-06-03 09:43:38 -0700940 return;
941 }
942
943 for (const auto& object : subtree)
944 {
Ed Tanous96825be2022-06-03 09:43:38 -0700945
Ed Tanous365a73f2023-02-24 12:16:49 -0800946 VmMode mode = parseObjectPathAndGetMode(object.first, resName);
947 if (mode != VmMode::Invalid)
Ed Tanous96825be2022-06-03 09:43:38 -0700948 {
Ed Tanous365a73f2023-02-24 12:16:49 -0800949 doEjectAction(asyncResp, service, resName,
950 mode == VmMode::Legacy);
Ed Tanous96825be2022-06-03 09:43:38 -0700951 }
952 }
953 BMCWEB_LOG_DEBUG << "Parent item not found";
954 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
955 },
956 service, "/xyz/openbmc_project/VirtualMedia",
957 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
George Liu2b731192023-01-11 16:27:13 +0800958 });
Ed Tanous96825be2022-06-03 09:43:38 -0700959}
960
961inline void handleManagersVirtualMediaCollectionGet(
962 crow::App& app, const crow::Request& req,
963 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
964 const std::string& name)
965{
966 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
967 {
968 return;
969 }
970 if (name != "bmc")
971 {
972 messages::resourceNotFound(asyncResp->res, "VirtualMedia", name);
973
974 return;
975 }
976
977 asyncResp->res.jsonValue["@odata.type"] =
978 "#VirtualMediaCollection.VirtualMediaCollection";
979 asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
Ed Tanousfdb20342022-06-03 09:56:52 -0700980 asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
981 "redfish", "v1", "Managers", name, "VirtualMedia");
Ed Tanous96825be2022-06-03 09:43:38 -0700982
George Liu2b731192023-01-11 16:27:13 +0800983 dbus::utility::getDbusObject(
984 "/xyz/openbmc_project/VirtualMedia", {},
985 [asyncResp, name](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -0700986 const dbus::utility::MapperGetObject& getObjectType) {
987 if (ec)
988 {
989 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
990 messages::internalError(asyncResp->res);
991
992 return;
993 }
994 std::string service = getObjectType.begin()->first;
995 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
996
997 getVmResourceList(asyncResp, service, name);
George Liu2b731192023-01-11 16:27:13 +0800998 });
Ed Tanous96825be2022-06-03 09:43:38 -0700999}
1000
1001inline void
1002 handleVirtualMediaGet(crow::App& app, const crow::Request& req,
1003 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1004 const std::string& name, const std::string& resName)
1005{
1006 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1007 {
1008 return;
1009 }
1010 if (name != "bmc")
1011 {
1012 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
1013
1014 return;
1015 }
1016
George Liu2b731192023-01-11 16:27:13 +08001017 dbus::utility::getDbusObject(
1018 "/xyz/openbmc_project/VirtualMedia", {},
Ed Tanous96825be2022-06-03 09:43:38 -07001019 [asyncResp, name,
George Liu2b731192023-01-11 16:27:13 +08001020 resName](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -07001021 const dbus::utility::MapperGetObject& getObjectType) {
1022 if (ec)
1023 {
1024 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
1025 messages::internalError(asyncResp->res);
1026
1027 return;
1028 }
1029 std::string service = getObjectType.begin()->first;
1030 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1031
1032 getVmData(asyncResp, service, name, resName);
George Liu2b731192023-01-11 16:27:13 +08001033 });
Ed Tanous96825be2022-06-03 09:43:38 -07001034}
1035
Ed Tanous22db1722021-06-09 10:53:51 -07001036inline void requestNBDVirtualMediaRoutes(App& app)
1037{
George Liu0fda0f12021-11-16 10:06:17 +08001038 BMCWEB_ROUTE(
1039 app,
1040 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
Ed Tanoused398212021-06-09 17:05:54 -07001041 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous96825be2022-06-03 09:43:38 -07001042 .methods(boost::beast::http::verb::post)(std::bind_front(
1043 handleManagersVirtualMediaActionInsertPost, std::ref(app)));
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +02001044
George Liu0fda0f12021-11-16 10:06:17 +08001045 BMCWEB_ROUTE(
1046 app,
1047 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
Ed Tanoused398212021-06-09 17:05:54 -07001048 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous96825be2022-06-03 09:43:38 -07001049 .methods(boost::beast::http::verb::post)(std::bind_front(
1050 handleManagersVirtualMediaActionEject, std::ref(app)));
Ed Tanous002d39b2022-05-31 08:59:27 -07001051
Ed Tanous22db1722021-06-09 10:53:51 -07001052 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
Ed Tanoused398212021-06-09 17:05:54 -07001053 .privileges(redfish::privileges::getVirtualMediaCollection)
Ed Tanous96825be2022-06-03 09:43:38 -07001054 .methods(boost::beast::http::verb::get)(std::bind_front(
1055 handleManagersVirtualMediaCollectionGet, std::ref(app)));
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001056
Ed Tanous22db1722021-06-09 10:53:51 -07001057 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001058 .privileges(redfish::privileges::getVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -07001059 .methods(boost::beast::http::verb::get)(
Ed Tanous96825be2022-06-03 09:43:38 -07001060 std::bind_front(handleVirtualMediaGet, std::ref(app)));
Ed Tanous22db1722021-06-09 10:53:51 -07001061}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001062
1063} // namespace redfish