blob: 56e26793d4f8d767c0ee8fb80b02bbee6fa5e334 [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>
Ed Tanousef4c65b2023-04-24 15:28:50 -070028#include <boost/url/format.hpp>
Anna Platash9e319cf2020-11-17 10:18:31 +010029#include <boost/url/url_view.hpp>
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020030
George Liu2b731192023-01-11 16:27:13 +080031#include <array>
32#include <string_view>
33
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020034namespace redfish
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020035{
Ed Tanous365a73f2023-02-24 12:16:49 -080036
37enum class VmMode
38{
39 Invalid,
40 Legacy,
41 Proxy
42};
43
44inline VmMode
45 parseObjectPathAndGetMode(const sdbusplus::message::object_path& itemPath,
46 const std::string& resName)
47{
48 std::string thisPath = itemPath.filename();
49 BMCWEB_LOG_DEBUG << "Filename: " << itemPath.str
50 << ", ThisPath: " << thisPath;
51
52 if (thisPath.empty())
53 {
54 return VmMode::Invalid;
55 }
56
57 if (thisPath != resName)
58 {
59 return VmMode::Invalid;
60 }
61
62 auto mode = itemPath.parent_path();
63 auto type = mode.parent_path();
64
65 if (mode.filename().empty() || type.filename().empty())
66 {
67 return VmMode::Invalid;
68 }
69
70 if (type.filename() != "VirtualMedia")
71 {
72 return VmMode::Invalid;
73 }
74 std::string modeStr = mode.filename();
75 if (modeStr == "Legacy")
76 {
77 return VmMode::Legacy;
78 }
79 if (modeStr == "Proxy")
80 {
81 return VmMode::Proxy;
82 }
83 return VmMode::Invalid;
84}
85
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +020086using CheckItemHandler =
87 std::function<void(const std::string& service, const std::string& resName,
88 const std::shared_ptr<bmcweb::AsyncResp>&,
George Liu70cbdf52023-03-04 12:07:25 +080089 const std::pair<sdbusplus::message::object_path,
90 dbus::utility::DBusInteracesMap>&)>;
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +020091
92inline void findAndParseObject(const std::string& service,
93 const std::string& resName,
94 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
95 CheckItemHandler&& handler)
96{
97 crow::connections::systemBus->async_method_call(
98 [service, resName, aResp,
Lakshmi Yadlapati746c5b82023-03-06 16:07:28 -060099 handler](const boost::system::error_code& ec,
George Liu70cbdf52023-03-04 12:07:25 +0800100 const dbus::utility::ManagedObjectType& subtree) {
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200101 if (ec)
102 {
103 BMCWEB_LOG_DEBUG << "DBUS response error";
104
105 return;
106 }
107
George Liu70cbdf52023-03-04 12:07:25 +0800108 for (const auto& item : subtree)
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200109 {
110 VmMode mode = parseObjectPathAndGetMode(item.first, resName);
111 if (mode != VmMode::Invalid)
112 {
113 handler(service, resName, aResp, item);
114 return;
115 }
116 }
117
118 BMCWEB_LOG_DEBUG << "Parent item not found";
119 aResp->res.result(boost::beast::http::status::not_found);
120 },
121 service, "/xyz/openbmc_project/VirtualMedia",
122 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
123}
124
Anna Platash9e319cf2020-11-17 10:18:31 +0100125/**
126 * @brief Function extracts transfer protocol name from URI.
127 */
Ed Tanous67df0732021-10-26 11:23:56 -0700128inline std::string getTransferProtocolTypeFromUri(const std::string& imageUri)
129{
130 boost::urls::result<boost::urls::url_view> url =
Ed Tanous079360a2022-06-29 10:05:19 -0700131 boost::urls::parse_uri(imageUri);
Ed Tanous67df0732021-10-26 11:23:56 -0700132 if (!url)
133 {
134 return "None";
135 }
Ed Tanous079360a2022-06-29 10:05:19 -0700136 std::string_view scheme = url->scheme();
Ed Tanous67df0732021-10-26 11:23:56 -0700137 if (scheme == "smb")
138 {
139 return "CIFS";
140 }
141 if (scheme == "https")
142 {
143 return "HTTPS";
144 }
145
146 return "None";
147}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200148
149/**
150 * @brief Read all known properties from VM object interfaces
151 */
Ed Tanous22db1722021-06-09 10:53:51 -0700152inline void
Ed Tanous8a592812022-06-04 09:06:59 -0700153 vmParseInterfaceObject(const dbus::utility::DBusInteracesMap& interfaces,
zhanghch058d1b46d2021-04-01 11:18:24 +0800154 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200155{
Ed Tanous8a592812022-06-04 09:06:59 -0700156 for (const auto& [interface, values] : interfaces)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200157 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800158 if (interface == "xyz.openbmc_project.VirtualMedia.MountPoint")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200159 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800160 for (const auto& [property, value] : values)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200161 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800162 if (property == "EndpointId")
163 {
164 const std::string* endpointIdValue =
165 std::get_if<std::string>(&value);
166 if (endpointIdValue == nullptr)
167 {
168 continue;
169 }
170 if (!endpointIdValue->empty())
171 {
172 // Proxy mode
173 aResp->res
174 .jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
175 *endpointIdValue;
176 aResp->res.jsonValue["TransferProtocolType"] = "OEM";
177 }
178 }
179 if (property == "ImageURL")
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200180 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100181 const std::string* imageUrlValue =
Ed Tanous711ac7a2021-12-20 09:34:41 -0800182 std::get_if<std::string>(&value);
Ed Tanous26f69762022-01-25 09:49:11 -0800183 if (imageUrlValue != nullptr && !imageUrlValue->empty())
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100184 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100185 std::filesystem::path filePath = *imageUrlValue;
186 if (!filePath.has_filename())
187 {
188 // this will handle https share, which not
189 // necessarily has to have filename given.
190 aResp->res.jsonValue["ImageName"] = "";
191 }
192 else
193 {
194 aResp->res.jsonValue["ImageName"] =
195 filePath.filename();
196 }
Przemyslaw Czarnowskida4784d2020-11-06 09:58:25 +0100197
Anna Platash9e319cf2020-11-17 10:18:31 +0100198 aResp->res.jsonValue["Image"] = *imageUrlValue;
Anna Platash9e319cf2020-11-17 10:18:31 +0100199 aResp->res.jsonValue["TransferProtocolType"] =
200 getTransferProtocolTypeFromUri(*imageUrlValue);
201
Ed Tanous739b87e2023-02-24 13:13:33 -0800202 aResp->res.jsonValue["ConnectedVia"] =
203 virtual_media::ConnectedVia::URI;
Anna Platash9e319cf2020-11-17 10:18:31 +0100204 }
205 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800206 if (property == "WriteProtected")
Anna Platash9e319cf2020-11-17 10:18:31 +0100207 {
Ed Tanous711ac7a2021-12-20 09:34:41 -0800208 const bool* writeProtectedValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800209 if (writeProtectedValue != nullptr)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200210 {
Anna Platash9e319cf2020-11-17 10:18:31 +0100211 aResp->res.jsonValue["WriteProtected"] =
212 *writeProtectedValue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200213 }
214 }
215 }
216 }
Ed Tanous711ac7a2021-12-20 09:34:41 -0800217 if (interface == "xyz.openbmc_project.VirtualMedia.Process")
218 {
219 for (const auto& [property, value] : values)
220 {
221 if (property == "Active")
222 {
223 const bool* activeValue = std::get_if<bool>(&value);
Ed Tanouse662eae2022-01-25 10:39:19 -0800224 if (activeValue == nullptr)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800225 {
226 BMCWEB_LOG_DEBUG << "Value Active not found";
227 return;
228 }
229 aResp->res.jsonValue["Inserted"] = *activeValue;
230
Ed Tanouse05aec52022-01-25 10:28:56 -0800231 if (*activeValue)
Ed Tanous711ac7a2021-12-20 09:34:41 -0800232 {
Ed Tanous739b87e2023-02-24 13:13:33 -0800233 aResp->res.jsonValue["ConnectedVia"] =
234 virtual_media::ConnectedVia::Applet;
Ed Tanous711ac7a2021-12-20 09:34:41 -0800235 }
236 }
237 }
238 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200239 }
240}
241
242/**
243 * @brief Fill template for Virtual Media Item.
244 */
Ed Tanous22db1722021-06-09 10:53:51 -0700245inline nlohmann::json vmItemTemplate(const std::string& name,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500246 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200247{
248 nlohmann::json item;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700249 item["@odata.id"] = boost::urls::format(
250 "/redfish/v1/Managers/{}/VirtualMedia/{}", name, resName);
Ed Tanous22db1722021-06-09 10:53:51 -0700251
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100252 item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200253 item["Name"] = "Virtual Removable Media";
254 item["Id"] = resName;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200255 item["WriteProtected"] = true;
Ed Tanous739b87e2023-02-24 13:13:33 -0800256 item["ConnectedVia"] = virtual_media::ConnectedVia::NotConnected;
Ed Tanous613dabe2022-07-09 11:17:36 -0700257 item["MediaTypes"] = nlohmann::json::array_t({"CD", "USBStick"});
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200258 item["TransferMethod"] = "Stream";
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100259 item["Oem"]["OpenBMC"]["@odata.type"] =
260 "#OemVirtualMedia.v1_0_0.VirtualMedia";
V-Sanjana15b89722023-05-11 16:27:03 +0530261 item["Oem"]["OpenBMC"]["@odata.id"] = boost::urls::format(
262 "/redfish/v1/Managers/{}/VirtualMedia/{}#/Oem/OpenBMC", name, resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200263
264 return item;
265}
266
267/**
268 * @brief Fills collection data
269 */
Ed Tanous22db1722021-06-09 10:53:51 -0700270inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500271 const std::string& service,
272 const std::string& name)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200273{
274 BMCWEB_LOG_DEBUG << "Get available Virtual Media resources.";
275 crow::connections::systemBus->async_method_call(
Ed Tanous02cad962022-06-30 16:50:15 -0700276 [name, aResp{std::move(aResp)}](
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800277 const boost::system::error_code& ec,
Ed Tanous02cad962022-06-30 16:50:15 -0700278 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700279 if (ec)
280 {
281 BMCWEB_LOG_DEBUG << "DBUS response error";
282 return;
283 }
284 nlohmann::json& members = aResp->res.jsonValue["Members"];
285 members = nlohmann::json::array();
286
287 for (const auto& object : subtree)
288 {
289 nlohmann::json item;
290 std::string path = object.first.filename();
291 if (path.empty())
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200292 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700293 continue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200294 }
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200295
Ed Tanousef4c65b2023-04-24 15:28:50 -0700296 item["@odata.id"] = boost::urls::format(
297 "/redfish/v1/Managers/{}/VirtualMedia/{}", name, path);
Ed Tanous002d39b2022-05-31 08:59:27 -0700298 members.emplace_back(std::move(item));
299 }
300 aResp->res.jsonValue["Members@odata.count"] = members.size();
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200301 },
302 service, "/xyz/openbmc_project/VirtualMedia",
303 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
304}
305
George Liu70cbdf52023-03-04 12:07:25 +0800306inline void
307 afterGetVmData(const std::string& name, const std::string& /*service*/,
308 const std::string& resName,
309 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
310 const std::pair<sdbusplus::message::object_path,
311 dbus::utility::DBusInteracesMap>& item)
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200312{
313 VmMode mode = parseObjectPathAndGetMode(item.first, resName);
314 if (mode == VmMode::Invalid)
315 {
316 return;
317 }
318
319 asyncResp->res.jsonValue = vmItemTemplate(name, resName);
320
321 // Check if dbus path is Legacy type
322 if (mode == VmMode::Legacy)
323 {
Ed Tanousef4c65b2023-04-24 15:28:50 -0700324 asyncResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
325 ["target"] = boost::urls::format(
326 "/redfish/v1/Managers/{}/VirtualMedia/{}/Actions/VirtualMedia.InsertMedia",
327 name, resName);
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200328 }
329
330 vmParseInterfaceObject(item.second, asyncResp);
331
Ed Tanousef4c65b2023-04-24 15:28:50 -0700332 asyncResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"]
333 ["target"] = boost::urls::format(
334 "/redfish/v1/Managers/{}/VirtualMedia/{}/Actions/VirtualMedia.EjectMedia",
335 name, resName);
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200336}
337
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200338/**
339 * @brief Fills data for specific resource
340 */
Ed Tanous22db1722021-06-09 10:53:51 -0700341inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500342 const std::string& service, const std::string& name,
343 const std::string& resName)
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200344{
345 BMCWEB_LOG_DEBUG << "Get Virtual Media resource data.";
346
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200347 findAndParseObject(service, resName, aResp,
George Liu70cbdf52023-03-04 12:07:25 +0800348 std::bind_front(afterGetVmData, name));
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200349}
350
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200351/**
Ed Tanous22db1722021-06-09 10:53:51 -0700352 * @brief Transfer protocols supported for InsertMedia action.
353 *
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200354 */
Ed Tanous22db1722021-06-09 10:53:51 -0700355enum class TransferProtocol
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200356{
Ed Tanous22db1722021-06-09 10:53:51 -0700357 https,
358 smb,
359 invalid
360};
361
362/**
363 * @brief Function extracts transfer protocol type from URI.
364 *
365 */
Ed Tanous67df0732021-10-26 11:23:56 -0700366inline std::optional<TransferProtocol>
Ed Tanousd9f466b2023-03-06 15:04:25 -0800367 getTransferProtocolFromUri(boost::urls::url_view imageUri)
Ed Tanous67df0732021-10-26 11:23:56 -0700368{
Ed Tanous079360a2022-06-29 10:05:19 -0700369 std::string_view scheme = imageUri.scheme();
Ed Tanous67df0732021-10-26 11:23:56 -0700370 if (scheme == "smb")
371 {
372 return TransferProtocol::smb;
373 }
374 if (scheme == "https")
375 {
376 return TransferProtocol::https;
377 }
378 if (!scheme.empty())
379 {
380 return TransferProtocol::invalid;
381 }
382
383 return {};
384}
Ed Tanous22db1722021-06-09 10:53:51 -0700385
386/**
387 * @brief Function convert transfer protocol from string param.
388 *
389 */
390inline std::optional<TransferProtocol> getTransferProtocolFromParam(
391 const std::optional<std::string>& transferProtocolType)
392{
393 if (transferProtocolType == std::nullopt)
Agata Olenderc6f4e012020-03-11 15:19:07 +0100394 {
Ed Tanous22db1722021-06-09 10:53:51 -0700395 return {};
Agata Olenderc6f4e012020-03-11 15:19:07 +0100396 }
397
Ed Tanous22db1722021-06-09 10:53:51 -0700398 if (*transferProtocolType == "CIFS")
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200399 {
Ed Tanous22db1722021-06-09 10:53:51 -0700400 return TransferProtocol::smb;
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200401 }
402
Ed Tanous22db1722021-06-09 10:53:51 -0700403 if (*transferProtocolType == "HTTPS")
404 {
405 return TransferProtocol::https;
406 }
407
408 return TransferProtocol::invalid;
409}
410
411/**
412 * @brief Function extends URI with transfer protocol type.
413 *
414 */
415inline std::string
416 getUriWithTransferProtocol(const std::string& imageUri,
417 const TransferProtocol& transferProtocol)
418{
419 if (transferProtocol == TransferProtocol::smb)
420 {
421 return "smb://" + imageUri;
422 }
423
424 if (transferProtocol == TransferProtocol::https)
425 {
426 return "https://" + imageUri;
427 }
428
429 return imageUri;
430}
431
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200432struct InsertMediaActionParams
433{
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200434 std::optional<std::string> imageUrl;
Przemyslaw Czarnowski1f2a40c2022-06-24 13:47:08 +0200435 std::optional<std::string> userName;
436 std::optional<std::string> password;
437 std::optional<std::string> transferMethod;
438 std::optional<std::string> transferProtocolType;
439 std::optional<bool> writeProtected = true;
440 std::optional<bool> inserted;
441};
442
Ed Tanous22db1722021-06-09 10:53:51 -0700443template <typename T>
444static void secureCleanup(T& value)
445{
Ed Tanous4ecc6182022-01-07 09:36:26 -0800446 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
Ed Tanous22db1722021-06-09 10:53:51 -0700447 auto raw = const_cast<typename T::value_type*>(value.data());
448 explicit_bzero(raw, value.size() * sizeof(*raw));
449}
450
451class Credentials
452{
453 public:
454 Credentials(std::string&& user, std::string&& password) :
455 userBuf(std::move(user)), passBuf(std::move(password))
456 {}
457
458 ~Credentials()
459 {
460 secureCleanup(userBuf);
461 secureCleanup(passBuf);
462 }
463
464 const std::string& user()
465 {
466 return userBuf;
467 }
468
469 const std::string& password()
470 {
471 return passBuf;
472 }
473
474 Credentials() = delete;
475 Credentials(const Credentials&) = delete;
476 Credentials& operator=(const Credentials&) = delete;
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800477 Credentials(Credentials&&) = delete;
478 Credentials& operator=(Credentials&&) = delete;
Ed Tanous22db1722021-06-09 10:53:51 -0700479
480 private:
481 std::string userBuf;
482 std::string passBuf;
483};
484
485class CredentialsProvider
486{
487 public:
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500488 template <typename T>
Ed Tanous22db1722021-06-09 10:53:51 -0700489 struct Deleter
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100490 {
Ed Tanous22db1722021-06-09 10:53:51 -0700491 void operator()(T* buff) const
492 {
493 if (buff)
494 {
495 secureCleanup(*buff);
496 delete buff;
497 }
498 }
499 };
500
501 using Buffer = std::vector<char>;
502 using SecureBuffer = std::unique_ptr<Buffer, Deleter<Buffer>>;
503 // Using explicit definition instead of std::function to avoid implicit
504 // conversions eg. stack copy instead of reference
505 using FormatterFunc = void(const std::string& username,
506 const std::string& password, Buffer& dest);
507
508 CredentialsProvider(std::string&& user, std::string&& password) :
509 credentials(std::move(user), std::move(password))
510 {}
511
512 const std::string& user()
513 {
514 return credentials.user();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100515 }
516
Ed Tanous22db1722021-06-09 10:53:51 -0700517 const std::string& password()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100518 {
Ed Tanous22db1722021-06-09 10:53:51 -0700519 return credentials.password();
520 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100521
Ed Tanous1917ee92022-06-30 22:30:50 -0700522 SecureBuffer pack(FormatterFunc* formatter)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100523 {
Ed Tanous22db1722021-06-09 10:53:51 -0700524 SecureBuffer packed{new Buffer{}};
Ed Tanouse662eae2022-01-25 10:39:19 -0800525 if (formatter != nullptr)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100526 {
Ed Tanous22db1722021-06-09 10:53:51 -0700527 formatter(credentials.user(), credentials.password(), *packed);
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100528 }
529
Ed Tanous22db1722021-06-09 10:53:51 -0700530 return packed;
531 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100532
Ed Tanous22db1722021-06-09 10:53:51 -0700533 private:
534 Credentials credentials;
535};
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100536
Ed Tanous22db1722021-06-09 10:53:51 -0700537// Wrapper for boost::async_pipe ensuring proper pipe cleanup
Ed Tanous0a483062022-07-11 10:18:50 -0700538class SecurePipe
Ed Tanous22db1722021-06-09 10:53:51 -0700539{
540 public:
541 using unix_fd = sdbusplus::message::unix_fd;
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100542
Ed Tanous0a483062022-07-11 10:18:50 -0700543 SecurePipe(boost::asio::io_context& io,
544 CredentialsProvider::SecureBuffer&& bufferIn) :
545 impl(io),
546 buffer{std::move(bufferIn)}
Ed Tanous22db1722021-06-09 10:53:51 -0700547 {}
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100548
Ed Tanous0a483062022-07-11 10:18:50 -0700549 ~SecurePipe()
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100550 {
Ed Tanous22db1722021-06-09 10:53:51 -0700551 // Named pipe needs to be explicitly removed
552 impl.close();
553 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100554
Ed Tanous0a483062022-07-11 10:18:50 -0700555 SecurePipe(const SecurePipe&) = delete;
556 SecurePipe(SecurePipe&&) = delete;
557 SecurePipe& operator=(const SecurePipe&) = delete;
558 SecurePipe& operator=(SecurePipe&&) = delete;
Ed Tanousecd6a3a2022-01-07 09:18:40 -0800559
Ed Tanous0a483062022-07-11 10:18:50 -0700560 unix_fd fd() const
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200561 {
Ed Tanous22db1722021-06-09 10:53:51 -0700562 return unix_fd{impl.native_source()};
563 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100564
Ed Tanous22db1722021-06-09 10:53:51 -0700565 template <typename WriteHandler>
566 void asyncWrite(WriteHandler&& handler)
567 {
Ed Tanous0a483062022-07-11 10:18:50 -0700568 impl.async_write_some(boost::asio::buffer(*buffer),
569 std::forward<WriteHandler>(handler));
Ed Tanous22db1722021-06-09 10:53:51 -0700570 }
571
572 const std::string name;
573 boost::process::async_pipe impl;
Ed Tanous0a483062022-07-11 10:18:50 -0700574 CredentialsProvider::SecureBuffer buffer;
Ed Tanous22db1722021-06-09 10:53:51 -0700575};
576
577/**
578 * @brief Function transceives data with dbus directly.
579 *
580 * All BMC state properties will be retrieved before sending reset request.
581 */
582inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
583 const std::string& service, const std::string& name,
584 const std::string& imageUrl, const bool rw,
585 std::string&& userName, std::string&& password)
586{
Ed Tanous22db1722021-06-09 10:53:51 -0700587 constexpr const size_t secretLimit = 1024;
588
589 std::shared_ptr<SecurePipe> secretPipe;
Ed Tanous168e20c2021-12-13 14:39:53 -0800590 dbus::utility::DbusVariantType unixFd = -1;
Ed Tanous22db1722021-06-09 10:53:51 -0700591
592 if (!userName.empty() || !password.empty())
593 {
594 // Encapsulate in safe buffer
595 CredentialsProvider credentials(std::move(userName),
596 std::move(password));
597
598 // Payload must contain data + NULL delimiters
599 if (credentials.user().size() + credentials.password().size() + 2 >
600 secretLimit)
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100601 {
Ed Tanous22db1722021-06-09 10:53:51 -0700602 BMCWEB_LOG_ERROR << "Credentials too long to handle";
603 messages::unrecognizedRequestBody(asyncResp->res);
604 return;
605 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100606
Ed Tanous22db1722021-06-09 10:53:51 -0700607 // Pack secret
608 auto secret = credentials.pack(
609 [](const auto& user, const auto& pass, auto& buff) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700610 std::copy(user.begin(), user.end(), std::back_inserter(buff));
611 buff.push_back('\0');
612 std::copy(pass.begin(), pass.end(), std::back_inserter(buff));
613 buff.push_back('\0');
614 });
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100615
Ed Tanous22db1722021-06-09 10:53:51 -0700616 // Open pipe
617 secretPipe = std::make_shared<SecurePipe>(
618 crow::connections::systemBus->get_io_context(), std::move(secret));
619 unixFd = secretPipe->fd();
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100620
Ed Tanous22db1722021-06-09 10:53:51 -0700621 // Pass secret over pipe
622 secretPipe->asyncWrite(
623 [asyncResp](const boost::system::error_code& ec, std::size_t) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700624 if (ec)
625 {
626 BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec;
627 messages::internalError(asyncResp->res);
628 }
629 });
Ed Tanous22db1722021-06-09 10:53:51 -0700630 }
Adrian Ambrożewicz988fb7b2020-01-13 18:52:46 +0100631
Ed Tanous22db1722021-06-09 10:53:51 -0700632 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800633 [asyncResp, secretPipe](const boost::system::error_code& ec,
Ed Tanous22db1722021-06-09 10:53:51 -0700634 bool success) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700635 if (ec)
636 {
637 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
638 messages::internalError(asyncResp->res);
639 }
640 else if (!success)
641 {
642 BMCWEB_LOG_ERROR << "Service responded with error";
643 messages::generalError(asyncResp->res);
644 }
Ed Tanous22db1722021-06-09 10:53:51 -0700645 },
646 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
647 "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw,
648 unixFd);
649}
650
651/**
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200652 * @brief Function validate parameters of insert media request.
653 *
654 */
655inline void validateParams(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
656 const std::string& service,
657 const std::string& resName,
658 InsertMediaActionParams& actionParams)
659{
660 BMCWEB_LOG_DEBUG << "Validation started";
661 // required param imageUrl must not be empty
662 if (!actionParams.imageUrl)
663 {
664 BMCWEB_LOG_ERROR << "Request action parameter Image is empty.";
665
666 messages::propertyValueFormatError(asyncResp->res, "<empty>", "Image");
667
668 return;
669 }
670
671 // optional param inserted must be true
672 if ((actionParams.inserted != std::nullopt) && !*actionParams.inserted)
673 {
674 BMCWEB_LOG_ERROR
675 << "Request action optional parameter Inserted must be true.";
676
677 messages::actionParameterNotSupported(asyncResp->res, "Inserted",
678 "InsertMedia");
679
680 return;
681 }
682
683 // optional param transferMethod must be stream
684 if ((actionParams.transferMethod != std::nullopt) &&
685 (*actionParams.transferMethod != "Stream"))
686 {
687 BMCWEB_LOG_ERROR << "Request action optional parameter "
688 "TransferMethod must be Stream.";
689
690 messages::actionParameterNotSupported(asyncResp->res, "TransferMethod",
691 "InsertMedia");
692
693 return;
694 }
695 boost::urls::result<boost::urls::url_view> url =
696 boost::urls::parse_uri(*actionParams.imageUrl);
697 if (!url)
698 {
699 messages::actionParameterValueFormatError(
700 asyncResp->res, *actionParams.imageUrl, "Image", "InsertMedia");
701 return;
702 }
703 std::optional<TransferProtocol> uriTransferProtocolType =
704 getTransferProtocolFromUri(*url);
705
706 std::optional<TransferProtocol> paramTransferProtocolType =
707 getTransferProtocolFromParam(actionParams.transferProtocolType);
708
709 // ImageUrl does not contain valid protocol type
710 if (*uriTransferProtocolType == TransferProtocol::invalid)
711 {
712 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
713 "contain specified protocol type from list: "
714 "(smb, https).";
715
716 messages::resourceAtUriInUnknownFormat(asyncResp->res, *url);
717
718 return;
719 }
720
721 // transferProtocolType should contain value from list
722 if (*paramTransferProtocolType == TransferProtocol::invalid)
723 {
724 BMCWEB_LOG_ERROR << "Request action parameter TransferProtocolType "
725 "must be provided with value from list: "
726 "(CIFS, HTTPS).";
727
728 messages::propertyValueNotInList(asyncResp->res,
729 *actionParams.transferProtocolType,
730 "TransferProtocolType");
731 return;
732 }
733
734 // valid transfer protocol not provided either with URI nor param
735 if ((uriTransferProtocolType == std::nullopt) &&
736 (paramTransferProtocolType == std::nullopt))
737 {
738 BMCWEB_LOG_ERROR << "Request action parameter ImageUrl must "
739 "contain specified protocol type or param "
740 "TransferProtocolType must be provided.";
741
742 messages::resourceAtUriInUnknownFormat(asyncResp->res, *url);
743
744 return;
745 }
746
747 // valid transfer protocol provided both with URI and param
748 if ((paramTransferProtocolType != std::nullopt) &&
749 (uriTransferProtocolType != std::nullopt))
750 {
751 // check if protocol is the same for URI and param
752 if (*paramTransferProtocolType != *uriTransferProtocolType)
753 {
754 BMCWEB_LOG_ERROR << "Request action parameter "
755 "TransferProtocolType must contain the "
756 "same protocol type as protocol type "
757 "provided with param imageUrl.";
758
759 messages::actionParameterValueTypeError(
760 asyncResp->res, *actionParams.transferProtocolType,
761 "TransferProtocolType", "InsertMedia");
762
763 return;
764 }
765 }
766
767 // validation passed, add protocol to URI if needed
768 if (uriTransferProtocolType == std::nullopt)
769 {
770 actionParams.imageUrl = getUriWithTransferProtocol(
771 *actionParams.imageUrl, *paramTransferProtocolType);
772 }
773
Jayaprakash Mutyala452bd8d2023-04-18 12:28:38 +0000774 if (!actionParams.userName)
775 {
776 actionParams.userName = "";
777 }
778
779 if (!actionParams.password)
780 {
781 actionParams.password = "";
782 }
783
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200784 doMountVmLegacy(asyncResp, service, resName, *actionParams.imageUrl,
785 !(*actionParams.writeProtected),
786 std::move(*actionParams.userName),
787 std::move(*actionParams.password));
788}
789
790/**
Ed Tanous22db1722021-06-09 10:53:51 -0700791 * @brief Function transceives data with dbus directly.
792 *
793 * All BMC state properties will be retrieved before sending reset request.
794 */
Ed Tanous24e740a2023-02-24 12:08:58 -0800795inline void doEjectAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
796 const std::string& service, const std::string& name,
797 bool legacy)
Ed Tanous22db1722021-06-09 10:53:51 -0700798{
Ed Tanous22db1722021-06-09 10:53:51 -0700799 // Legacy mount requires parameter with image
800 if (legacy)
801 {
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100802 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800803 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700804 if (ec)
805 {
806 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700807
Ed Tanous002d39b2022-05-31 08:59:27 -0700808 messages::internalError(asyncResp->res);
809 return;
810 }
Adrian Ambrożewiczd6da5be2020-01-13 18:31:01 +0100811 },
812 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
Ed Tanous22db1722021-06-09 10:53:51 -0700813 "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200814 }
Ed Tanous22db1722021-06-09 10:53:51 -0700815 else // proxy
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200816 {
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200817 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800818 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700819 if (ec)
820 {
821 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
Ed Tanous22db1722021-06-09 10:53:51 -0700822
Ed Tanous002d39b2022-05-31 08:59:27 -0700823 messages::internalError(asyncResp->res);
824 return;
825 }
Ed Tanous22db1722021-06-09 10:53:51 -0700826 },
827 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
828 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
829 }
830}
831
Ed Tanous96825be2022-06-03 09:43:38 -0700832inline void handleManagersVirtualMediaActionInsertPost(
833 crow::App& app, const crow::Request& req,
834 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
835 const std::string& name, const std::string& resName)
836{
837 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
838 {
839 return;
840 }
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200841
842 constexpr std::string_view action = "VirtualMedia.InsertMedia";
Ed Tanous96825be2022-06-03 09:43:38 -0700843 if (name != "bmc")
844 {
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200845 messages::resourceNotFound(asyncResp->res, action, resName);
Ed Tanous96825be2022-06-03 09:43:38 -0700846
847 return;
848 }
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200849 InsertMediaActionParams actionParams;
Ed Tanous96825be2022-06-03 09:43:38 -0700850
Przemyslaw Czarnowski120fa862022-06-24 15:10:48 +0200851 // Read obligatory parameters (url of image)
Ed Tanous96825be2022-06-03 09:43:38 -0700852 if (!json_util::readJsonAction(
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200853 req, asyncResp->res, "Image", actionParams.imageUrl,
854 "WriteProtected", actionParams.writeProtected, "UserName",
855 actionParams.userName, "Password", actionParams.password,
856 "Inserted", actionParams.inserted, "TransferMethod",
857 actionParams.transferMethod, "TransferProtocolType",
858 actionParams.transferProtocolType))
Ed Tanous96825be2022-06-03 09:43:38 -0700859 {
860 return;
861 }
862
George Liu2b731192023-01-11 16:27:13 +0800863 dbus::utility::getDbusObject(
864 "/xyz/openbmc_project/VirtualMedia", {},
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200865 [asyncResp, action, actionParams,
George Liu2b731192023-01-11 16:27:13 +0800866 resName](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -0700867 const dbus::utility::MapperGetObject& getObjectType) mutable {
868 if (ec)
869 {
870 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200871 messages::resourceNotFound(asyncResp->res, action, resName);
Ed Tanous96825be2022-06-03 09:43:38 -0700872
873 return;
874 }
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200875
Ed Tanous96825be2022-06-03 09:43:38 -0700876 std::string service = getObjectType.begin()->first;
877 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
878
879 crow::connections::systemBus->async_method_call(
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200880 [service, resName, action, actionParams,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800881 asyncResp](const boost::system::error_code& ec2,
Ed Tanous96825be2022-06-03 09:43:38 -0700882 dbus::utility::ManagedObjectType& subtree) mutable {
Ed Tanous8a592812022-06-04 09:06:59 -0700883 if (ec2)
Ed Tanous96825be2022-06-03 09:43:38 -0700884 {
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200885 // Not possible in proxy mode
886 BMCWEB_LOG_DEBUG << "InsertMedia not "
887 "allowed in proxy mode";
888 messages::resourceNotFound(asyncResp->res, action, resName);
Ed Tanous96825be2022-06-03 09:43:38 -0700889
890 return;
891 }
Ed Tanous96825be2022-06-03 09:43:38 -0700892 for (const auto& object : subtree)
893 {
Ed Tanous365a73f2023-02-24 12:16:49 -0800894 VmMode mode = parseObjectPathAndGetMode(object.first, resName);
Boleslaw Ogonczyk Makowski5880f0c2023-04-14 15:32:40 +0200895 if (mode == VmMode::Legacy)
Ed Tanous96825be2022-06-03 09:43:38 -0700896 {
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200897 validateParams(asyncResp, service, resName, actionParams);
Ed Tanous96825be2022-06-03 09:43:38 -0700898
899 return;
900 }
901 }
902 BMCWEB_LOG_DEBUG << "Parent item not found";
903 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
904 },
905 service, "/xyz/openbmc_project/VirtualMedia",
906 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
George Liu2b731192023-01-11 16:27:13 +0800907 });
Ed Tanous96825be2022-06-03 09:43:38 -0700908}
909
910inline void handleManagersVirtualMediaActionEject(
911 crow::App& app, const crow::Request& req,
912 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
913 const std::string& managerName, const std::string& resName)
914{
915 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
916 {
917 return;
918 }
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200919
920 constexpr std::string_view action = "VirtualMedia.EjectMedia";
Ed Tanous96825be2022-06-03 09:43:38 -0700921 if (managerName != "bmc")
922 {
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200923 messages::resourceNotFound(asyncResp->res, action, resName);
Ed Tanous96825be2022-06-03 09:43:38 -0700924
925 return;
926 }
927
George Liu2b731192023-01-11 16:27:13 +0800928 dbus::utility::getDbusObject(
929 "/xyz/openbmc_project/VirtualMedia", {},
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200930 [asyncResp, action,
George Liu2b731192023-01-11 16:27:13 +0800931 resName](const boost::system::error_code& ec2,
Ed Tanous96825be2022-06-03 09:43:38 -0700932 const dbus::utility::MapperGetObject& getObjectType) {
Ed Tanous8a592812022-06-04 09:06:59 -0700933 if (ec2)
Ed Tanous96825be2022-06-03 09:43:38 -0700934 {
Ed Tanous8a592812022-06-04 09:06:59 -0700935 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec2;
Ed Tanous96825be2022-06-03 09:43:38 -0700936 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(
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200944 [resName, service, action,
945 asyncResp](const boost::system::error_code& ec,
946 const dbus::utility::ManagedObjectType& subtree) {
Ed Tanous96825be2022-06-03 09:43:38 -0700947 if (ec)
948 {
Przemyslaw Czarnowski79fdf632022-06-28 18:11:59 +0200949 BMCWEB_LOG_ERROR << "ObjectMapper : No Service found";
950 messages::resourceNotFound(asyncResp->res, action, resName);
Ed Tanous96825be2022-06-03 09:43:38 -0700951 return;
952 }
953
954 for (const auto& object : subtree)
955 {
Ed Tanous365a73f2023-02-24 12:16:49 -0800956 VmMode mode = parseObjectPathAndGetMode(object.first, resName);
957 if (mode != VmMode::Invalid)
Ed Tanous96825be2022-06-03 09:43:38 -0700958 {
Ed Tanous365a73f2023-02-24 12:16:49 -0800959 doEjectAction(asyncResp, service, resName,
960 mode == VmMode::Legacy);
Boleslaw Ogonczyk Makowski5880f0c2023-04-14 15:32:40 +0200961 return;
Ed Tanous96825be2022-06-03 09:43:38 -0700962 }
963 }
964 BMCWEB_LOG_DEBUG << "Parent item not found";
965 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
966 },
967 service, "/xyz/openbmc_project/VirtualMedia",
968 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
George Liu2b731192023-01-11 16:27:13 +0800969 });
Ed Tanous96825be2022-06-03 09:43:38 -0700970}
971
972inline void handleManagersVirtualMediaCollectionGet(
973 crow::App& app, const crow::Request& req,
974 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
975 const std::string& name)
976{
977 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
978 {
979 return;
980 }
981 if (name != "bmc")
982 {
983 messages::resourceNotFound(asyncResp->res, "VirtualMedia", name);
984
985 return;
986 }
987
988 asyncResp->res.jsonValue["@odata.type"] =
989 "#VirtualMediaCollection.VirtualMediaCollection";
990 asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
Ed Tanousef4c65b2023-04-24 15:28:50 -0700991 asyncResp->res.jsonValue["@odata.id"] =
992 boost::urls::format("/redfish/v1/Managers/{}/VirtualMedia", name);
Ed Tanous96825be2022-06-03 09:43:38 -0700993
George Liu2b731192023-01-11 16:27:13 +0800994 dbus::utility::getDbusObject(
995 "/xyz/openbmc_project/VirtualMedia", {},
996 [asyncResp, name](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -0700997 const dbus::utility::MapperGetObject& getObjectType) {
998 if (ec)
999 {
1000 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
1001 messages::internalError(asyncResp->res);
1002
1003 return;
1004 }
1005 std::string service = getObjectType.begin()->first;
1006 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1007
1008 getVmResourceList(asyncResp, service, name);
George Liu2b731192023-01-11 16:27:13 +08001009 });
Ed Tanous96825be2022-06-03 09:43:38 -07001010}
1011
1012inline void
1013 handleVirtualMediaGet(crow::App& app, const crow::Request& req,
1014 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1015 const std::string& name, const std::string& resName)
1016{
1017 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1018 {
1019 return;
1020 }
1021 if (name != "bmc")
1022 {
1023 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
1024
1025 return;
1026 }
1027
George Liu2b731192023-01-11 16:27:13 +08001028 dbus::utility::getDbusObject(
1029 "/xyz/openbmc_project/VirtualMedia", {},
Ed Tanous96825be2022-06-03 09:43:38 -07001030 [asyncResp, name,
George Liu2b731192023-01-11 16:27:13 +08001031 resName](const boost::system::error_code& ec,
Ed Tanous96825be2022-06-03 09:43:38 -07001032 const dbus::utility::MapperGetObject& getObjectType) {
1033 if (ec)
1034 {
1035 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " << ec;
1036 messages::internalError(asyncResp->res);
1037
1038 return;
1039 }
1040 std::string service = getObjectType.begin()->first;
1041 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
1042
1043 getVmData(asyncResp, service, name, resName);
George Liu2b731192023-01-11 16:27:13 +08001044 });
Ed Tanous96825be2022-06-03 09:43:38 -07001045}
1046
Ed Tanous22db1722021-06-09 10:53:51 -07001047inline void requestNBDVirtualMediaRoutes(App& app)
1048{
George Liu0fda0f12021-11-16 10:06:17 +08001049 BMCWEB_ROUTE(
1050 app,
1051 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.InsertMedia")
Ed Tanoused398212021-06-09 17:05:54 -07001052 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous96825be2022-06-03 09:43:38 -07001053 .methods(boost::beast::http::verb::post)(std::bind_front(
1054 handleManagersVirtualMediaActionInsertPost, std::ref(app)));
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +02001055
George Liu0fda0f12021-11-16 10:06:17 +08001056 BMCWEB_ROUTE(
1057 app,
1058 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/VirtualMedia.EjectMedia")
Ed Tanoused398212021-06-09 17:05:54 -07001059 .privileges(redfish::privileges::postVirtualMedia)
Ed Tanous96825be2022-06-03 09:43:38 -07001060 .methods(boost::beast::http::verb::post)(std::bind_front(
1061 handleManagersVirtualMediaActionEject, std::ref(app)));
Ed Tanous002d39b2022-05-31 08:59:27 -07001062
Ed Tanous22db1722021-06-09 10:53:51 -07001063 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/")
Ed Tanoused398212021-06-09 17:05:54 -07001064 .privileges(redfish::privileges::getVirtualMediaCollection)
Ed Tanous96825be2022-06-03 09:43:38 -07001065 .methods(boost::beast::http::verb::get)(std::bind_front(
1066 handleManagersVirtualMediaCollectionGet, std::ref(app)));
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001067
Ed Tanous22db1722021-06-09 10:53:51 -07001068 BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07001069 .privileges(redfish::privileges::getVirtualMedia)
Ed Tanous22db1722021-06-09 10:53:51 -07001070 .methods(boost::beast::http::verb::get)(
Ed Tanous96825be2022-06-03 09:43:38 -07001071 std::bind_front(handleVirtualMediaGet, std::ref(app)));
Ed Tanous22db1722021-06-09 10:53:51 -07001072}
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +02001073
1074} // namespace redfish