blob: 6e83973669bfb334d2b4034ec1acae39c7be01ea [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
18#include <boost/container/flat_map.hpp>
19#include <node.hpp>
20#include <utils/json_utils.hpp>
21// for GetObjectType and ManagedObjectType
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +020022#include <account_service.hpp>
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020023
24namespace redfish
25
26{
27
28/**
29 * @brief Read all known properties from VM object interfaces
30 */
31static void vmParseInterfaceObject(const DbusInterfaceType &interface,
32 std::shared_ptr<AsyncResp> aResp)
33{
34 const auto mountPointIface =
35 interface.find("xyz.openbmc_project.VirtualMedia.MountPoint");
36 if (mountPointIface == interface.cend())
37 {
38 BMCWEB_LOG_DEBUG << "Interface MountPoint not found";
39 return;
40 }
41
42 const auto processIface =
43 interface.find("xyz.openbmc_project.VirtualMedia.Process");
44 if (processIface == interface.cend())
45 {
46 BMCWEB_LOG_DEBUG << "Interface Process not found";
47 return;
48 }
49
50 const auto endpointIdProperty = mountPointIface->second.find("EndpointId");
51 if (endpointIdProperty == mountPointIface->second.cend())
52 {
53 BMCWEB_LOG_DEBUG << "Property EndpointId not found";
54 return;
55 }
56
57 const auto activeProperty = processIface->second.find("Active");
58 if (activeProperty == processIface->second.cend())
59 {
60 BMCWEB_LOG_DEBUG << "Property Active not found";
61 return;
62 }
63
64 const bool *activeValue = std::get_if<bool>(&activeProperty->second);
65 if (!activeValue)
66 {
67 BMCWEB_LOG_DEBUG << "Value Active not found";
68 return;
69 }
70
71 const std::string *endpointIdValue =
72 std::get_if<std::string>(&endpointIdProperty->second);
73 if (endpointIdValue)
74 {
75 if (!endpointIdValue->empty())
76 {
77 // Proxy mode
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +010078 aResp->res.jsonValue["Oem"]["OpenBMC"]["WebSocketEndpoint"] =
79 *endpointIdValue;
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +020080 aResp->res.jsonValue["TransferProtocolType"] = "OEM";
81 aResp->res.jsonValue["Inserted"] = *activeValue;
82 if (*activeValue == true)
83 {
84 aResp->res.jsonValue["ConnectedVia"] = "Applet";
85 }
86 }
87 else
88 {
89 // Legacy mode
90 const auto imageUrlProperty =
91 mountPointIface->second.find("ImageURL");
92 if (imageUrlProperty != processIface->second.cend())
93 {
94 const std::string *imageUrlValue =
95 std::get_if<std::string>(&imageUrlProperty->second);
96 if (imageUrlValue && !imageUrlValue->empty())
97 {
98 aResp->res.jsonValue["ImageName"] = *imageUrlValue;
99 aResp->res.jsonValue["Inserted"] = *activeValue;
100 if (*activeValue == true)
101 {
102 aResp->res.jsonValue["ConnectedVia"] = "URI";
103 }
104 }
105 }
106 }
107 }
108}
109
110/**
111 * @brief Fill template for Virtual Media Item.
112 */
113static nlohmann::json vmItemTemplate(const std::string &name,
114 const std::string &resName)
115{
116 nlohmann::json item;
117 item["@odata.id"] =
118 "/redfish/v1/Managers/" + name + "/VirtualMedia/" + resName;
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100119 item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200120 item["Name"] = "Virtual Removable Media";
121 item["Id"] = resName;
122 item["Image"] = nullptr;
123 item["Inserted"] = nullptr;
124 item["ImageName"] = nullptr;
125 item["WriteProtected"] = true;
126 item["ConnectedVia"] = "NotConnected";
127 item["MediaTypes"] = {"CD", "USBStick"};
128 item["TransferMethod"] = "Stream";
129 item["TransferProtocolType"] = nullptr;
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100130 item["Oem"]["OpenBmc"]["WebSocketEndpoint"] = nullptr;
131 item["Oem"]["OpenBMC"]["@odata.type"] =
132 "#OemVirtualMedia.v1_0_0.VirtualMedia";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200133
134 return item;
135}
136
137/**
138 * @brief Fills collection data
139 */
140static void getVmResourceList(std::shared_ptr<AsyncResp> aResp,
141 const std::string &service,
142 const std::string &name)
143{
144 BMCWEB_LOG_DEBUG << "Get available Virtual Media resources.";
145 crow::connections::systemBus->async_method_call(
146 [name, aResp{std::move(aResp)}](const boost::system::error_code ec,
147 ManagedObjectType &subtree) {
148 if (ec)
149 {
150 BMCWEB_LOG_DEBUG << "DBUS response error";
151 return;
152 }
153 nlohmann::json &members = aResp->res.jsonValue["Members"];
154 members = nlohmann::json::array();
155
156 for (const auto &object : subtree)
157 {
158 nlohmann::json item;
159 const std::string &path =
160 static_cast<const std::string &>(object.first);
161 std::size_t lastIndex = path.rfind("/");
162 if (lastIndex == std::string::npos)
163 {
164 continue;
165 }
166
167 lastIndex += 1;
168
169 item["@odata.id"] = "/redfish/v1/Managers/" + name +
170 "/VirtualMedia/" + path.substr(lastIndex);
171
172 members.emplace_back(std::move(item));
173 }
174 aResp->res.jsonValue["Members@odata.count"] = members.size();
175 },
176 service, "/xyz/openbmc_project/VirtualMedia",
177 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
178}
179
180/**
181 * @brief Fills data for specific resource
182 */
183static void getVmData(std::shared_ptr<AsyncResp> aResp,
184 const std::string &service, const std::string &name,
185 const std::string &resName)
186{
187 BMCWEB_LOG_DEBUG << "Get Virtual Media resource data.";
188
189 crow::connections::systemBus->async_method_call(
190 [resName, name, aResp](const boost::system::error_code ec,
191 ManagedObjectType &subtree) {
192 if (ec)
193 {
194 BMCWEB_LOG_DEBUG << "DBUS response error";
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200195
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200196 return;
197 }
198
199 for (auto &item : subtree)
200 {
201 const std::string &path =
202 static_cast<const std::string &>(item.first);
203
204 std::size_t lastItem = path.rfind("/");
205 if (lastItem == std::string::npos)
206 {
207 continue;
208 }
209
210 if (path.substr(lastItem + 1) != resName)
211 {
212 continue;
213 }
214
215 aResp->res.jsonValue = vmItemTemplate(name, resName);
216
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200217 // Check if dbus path is Legacy type
218 if (path.find("VirtualMedia/Legacy") != std::string::npos)
219 {
220 aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
221 ["target"] =
222 "/redfish/v1/Managers/" + name + "/VirtualMedia/" +
223 resName + "/Actions/VirtualMedia.InsertMedia";
224 }
225
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200226 vmParseInterfaceObject(item.second, aResp);
227
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200228 aResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"]
229 ["target"] =
230 "/redfish/v1/Managers/" + name + "/VirtualMedia/" +
231 resName + "/Actions/VirtualMedia.EjectMedia";
232
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200233 return;
234 }
235
236 messages::resourceNotFound(
Przemyslaw Czarnowskid04ba322020-01-21 12:41:56 +0100237 aResp->res, "#VirtualMedia.v1_3_0.VirtualMedia", resName);
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200238 },
239 service, "/xyz/openbmc_project/VirtualMedia",
240 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
241}
242
Przemyslaw Czarnowskie13c2762019-09-02 17:32:43 +0200243/**
244 @brief InsertMedia action class
245 */
246class VirtualMediaActionInsertMedia : public Node
247{
248 public:
249 VirtualMediaActionInsertMedia(CrowApp &app) :
250 Node(app,
251 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/"
252 "VirtualMedia.InsertMedia",
253 std::string(), std::string())
254 {
255 entityPrivileges = {
256 {boost::beast::http::verb::get, {{"Login"}}},
257 {boost::beast::http::verb::head, {{"Login"}}},
258 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
259 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
260 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
261 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
262 }
263
264 private:
265 /**
266 * @brief Function handles POST method request.
267 *
268 * Analyzes POST body message before sends Reset request data to dbus.
269 */
270 void doPost(crow::Response &res, const crow::Request &req,
271 const std::vector<std::string> &params) override
272 {
273 auto aResp = std::make_shared<AsyncResp>(res);
274
275 if (params.size() != 2)
276 {
277 messages::internalError(res);
278 return;
279 }
280
281 // take resource name from URL
282 const std::string &resName = params[1];
283
284 if (params[0] != "bmc")
285 {
286 messages::resourceNotFound(res, "VirtualMedia.Insert", resName);
287
288 return;
289 }
290
291 crow::connections::systemBus->async_method_call(
292 [this, aResp{std::move(aResp)}, req,
293 resName](const boost::system::error_code ec,
294 const GetObjectType &getObjectType) {
295 if (ec)
296 {
297 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: "
298 << ec;
299 messages::internalError(aResp->res);
300
301 return;
302 }
303 std::string service = getObjectType.begin()->first;
304 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
305
306 crow::connections::systemBus->async_method_call(
307 [this, service, resName, req, aResp{std::move(aResp)}](
308 const boost::system::error_code ec,
309 ManagedObjectType &subtree) {
310 if (ec)
311 {
312 BMCWEB_LOG_DEBUG << "DBUS response error";
313
314 return;
315 }
316
317 for (const auto &object : subtree)
318 {
319 const std::string &path =
320 static_cast<const std::string &>(object.first);
321
322 std::size_t lastIndex = path.rfind("/");
323 if (lastIndex == std::string::npos)
324 {
325 continue;
326 }
327
328 lastIndex += 1;
329
330 if (path.substr(lastIndex) == resName)
331 {
332 lastIndex = path.rfind("Proxy");
333 if (lastIndex != std::string::npos)
334 {
335 // Not possible in proxy mode
336 BMCWEB_LOG_DEBUG << "InsertMedia not "
337 "allowed in proxy mode";
338 messages::resourceNotFound(
339 aResp->res, "VirtualMedia.InsertMedia",
340 resName);
341
342 return;
343 }
344
345 lastIndex = path.rfind("Legacy");
346 if (lastIndex != std::string::npos)
347 {
348 // Legacy mode
349 std::string imageUrl;
350
351 // Read obligatory paramters (url of image)
352 if (!json_util::readJson(req, aResp->res,
353 "Image", imageUrl))
354 {
355 BMCWEB_LOG_DEBUG
356 << "Image is not provided";
357 return;
358 }
359
360 // must not be empty
361 if (imageUrl.size() == 0)
362 {
363 BMCWEB_LOG_ERROR
364 << "Request action parameter "
365 "Image is empty.";
366 messages::propertyValueFormatError(
367 aResp->res, "<empty>", "Image");
368
369 return;
370 }
371
372 // manager is irrelevant for VirtualMedia
373 // dbus calls
374 doVmAction(std::move(aResp), service,
375 resName, true, imageUrl);
376
377 return;
378 }
379 }
380 }
381 BMCWEB_LOG_DEBUG << "Parent item not found";
382 messages::resourceNotFound(aResp->res, "VirtualMedia",
383 resName);
384 },
385 service, "/xyz/openbmc_project/VirtualMedia",
386 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
387 },
388 "xyz.openbmc_project.ObjectMapper",
389 "/xyz/openbmc_project/object_mapper",
390 "xyz.openbmc_project.ObjectMapper", "GetObject",
391 "/xyz/openbmc_project/VirtualMedia", std::array<const char *, 0>());
392 }
393
394 /**
395 * @brief Function transceives data with dbus directly.
396 *
397 * All BMC state properties will be retrieved before sending reset request.
398 */
399 void doVmAction(std::shared_ptr<AsyncResp> asyncResp,
400 const std::string &service, const std::string &name,
401 bool legacy, const std::string &imageUrl)
402 {
403
404 // Legacy mount requires parameter with image
405 if (legacy)
406 {
407 crow::connections::systemBus->async_method_call(
408 [asyncResp](const boost::system::error_code ec) {
409 if (ec)
410 {
411 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
412 messages::internalError(asyncResp->res);
413
414 return;
415 }
416 },
417 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
418 "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl);
419 }
420 else // proxy
421 {
422 crow::connections::systemBus->async_method_call(
423 [asyncResp](const boost::system::error_code ec) {
424 if (ec)
425 {
426 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
427 messages::internalError(asyncResp->res);
428
429 return;
430 }
431 },
432 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
433 "xyz.openbmc_project.VirtualMedia.Proxy", "Mount");
434 }
435 }
436};
437
438/**
439 @brief EjectMedia action class
440 */
441class VirtualMediaActionEjectMedia : public Node
442{
443 public:
444 VirtualMediaActionEjectMedia(CrowApp &app) :
445 Node(app,
446 "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/"
447 "VirtualMedia.EjectMedia",
448 std::string(), std::string())
449 {
450 entityPrivileges = {
451 {boost::beast::http::verb::get, {{"Login"}}},
452 {boost::beast::http::verb::head, {{"Login"}}},
453 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
454 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
455 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
456 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
457 }
458
459 private:
460 /**
461 * @brief Function handles POST method request.
462 *
463 * Analyzes POST body message before sends Reset request data to dbus.
464 */
465 void doPost(crow::Response &res, const crow::Request &req,
466 const std::vector<std::string> &params) override
467 {
468 auto aResp = std::make_shared<AsyncResp>(res);
469
470 if (params.size() != 2)
471 {
472 messages::internalError(res);
473 return;
474 }
475
476 // take resource name from URL
477 const std::string &resName = params[1];
478
479 if (params[0] != "bmc")
480 {
481 messages::resourceNotFound(res, "VirtualMedia.Eject", resName);
482
483 return;
484 }
485
486 crow::connections::systemBus->async_method_call(
487 [this, aResp{std::move(aResp)}, req,
488 resName](const boost::system::error_code ec,
489 const GetObjectType &getObjectType) {
490 if (ec)
491 {
492 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: "
493 << ec;
494 messages::internalError(aResp->res);
495
496 return;
497 }
498 std::string service = getObjectType.begin()->first;
499 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
500
501 crow::connections::systemBus->async_method_call(
502 [this, resName, service, req, aResp{std::move(aResp)}](
503 const boost::system::error_code ec,
504 ManagedObjectType &subtree) {
505 if (ec)
506 {
507 BMCWEB_LOG_DEBUG << "DBUS response error";
508
509 return;
510 }
511
512 for (const auto &object : subtree)
513 {
514 const std::string &path =
515 static_cast<const std::string &>(object.first);
516
517 std::size_t lastIndex = path.rfind("/");
518 if (lastIndex == std::string::npos)
519 {
520 continue;
521 }
522
523 lastIndex += 1;
524
525 if (path.substr(lastIndex) == resName)
526 {
527 lastIndex = path.rfind("Proxy");
528 if (lastIndex != std::string::npos)
529 {
530 // Proxy mode
531 doVmAction(std::move(aResp), service,
532 resName, false);
533 }
534
535 lastIndex = path.rfind("Legacy");
536 if (lastIndex != std::string::npos)
537 {
538 // Legacy mode
539 doVmAction(std::move(aResp), service,
540 resName, true);
541 }
542
543 return;
544 }
545 }
546 BMCWEB_LOG_DEBUG << "Parent item not found";
547 messages::resourceNotFound(aResp->res, "VirtualMedia",
548 resName);
549 },
550 service, "/xyz/openbmc_project/VirtualMedia",
551 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
552 },
553 "xyz.openbmc_project.ObjectMapper",
554 "/xyz/openbmc_project/object_mapper",
555 "xyz.openbmc_project.ObjectMapper", "GetObject",
556 "/xyz/openbmc_project/VirtualMedia", std::array<const char *, 0>());
557 }
558
559 /**
560 * @brief Function transceives data with dbus directly.
561 *
562 * All BMC state properties will be retrieved before sending reset request.
563 */
564 void doVmAction(std::shared_ptr<AsyncResp> asyncResp,
565 const std::string &service, const std::string &name,
566 bool legacy)
567 {
568
569 // Legacy mount requires parameter with image
570 if (legacy)
571 {
572 crow::connections::systemBus->async_method_call(
573 [asyncResp](const boost::system::error_code ec) {
574 if (ec)
575 {
576 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
577
578 messages::internalError(asyncResp->res);
579 return;
580 }
581 },
582 service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
583 "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
584 }
585 else // proxy
586 {
587 crow::connections::systemBus->async_method_call(
588 [asyncResp](const boost::system::error_code ec) {
589 if (ec)
590 {
591 BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec;
592
593 messages::internalError(asyncResp->res);
594 return;
595 }
596 },
597 service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
598 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
599 }
600 }
601};
602
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200603class VirtualMediaCollection : public Node
604{
605 public:
606 /*
607 * Default Constructor
608 */
609 VirtualMediaCollection(CrowApp &app) :
610 Node(app, "/redfish/v1/Managers/<str>/VirtualMedia/", std::string())
611 {
612 entityPrivileges = {
613 {boost::beast::http::verb::get, {{"Login"}}},
614 {boost::beast::http::verb::head, {{"Login"}}},
615 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
616 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
617 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
618 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
619 }
620
621 private:
622 /**
623 * Functions triggers appropriate requests on DBus
624 */
625 void doGet(crow::Response &res, const crow::Request &req,
626 const std::vector<std::string> &params) override
627 {
628 auto asyncResp = std::make_shared<AsyncResp>(res);
629
630 // Check if there is required param, truly entering this shall be
631 // impossible
632 if (params.size() != 1)
633 {
634 messages::internalError(res);
635
636 return;
637 }
638
639 const std::string &name = params[0];
640
641 if (name != "bmc")
642 {
643 messages::resourceNotFound(asyncResp->res, "VirtualMedia", name);
644
645 return;
646 }
647
648 res.jsonValue["@odata.type"] =
649 "#VirtualMediaCollection.VirtualMediaCollection";
650 res.jsonValue["Name"] = "Virtual Media Services";
Przemyslaw Czarnowski107077d2019-07-11 10:16:43 +0200651 res.jsonValue["@odata.id"] =
652 "/redfish/v1/Managers/" + name + "/VirtualMedia/";
653
654 crow::connections::systemBus->async_method_call(
655 [asyncResp, name](const boost::system::error_code ec,
656 const GetObjectType &getObjectType) {
657 if (ec)
658 {
659 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: "
660 << ec;
661 messages::internalError(asyncResp->res);
662
663 return;
664 }
665 std::string service = getObjectType.begin()->first;
666 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
667
668 getVmResourceList(asyncResp, service, name);
669 },
670 "xyz.openbmc_project.ObjectMapper",
671 "/xyz/openbmc_project/object_mapper",
672 "xyz.openbmc_project.ObjectMapper", "GetObject",
673 "/xyz/openbmc_project/VirtualMedia", std::array<const char *, 0>());
674 }
675};
676
677class VirtualMedia : public Node
678{
679 public:
680 /*
681 * Default Constructor
682 */
683 VirtualMedia(CrowApp &app) :
684 Node(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/",
685 std::string(), std::string())
686 {
687 entityPrivileges = {
688 {boost::beast::http::verb::get, {{"Login"}}},
689 {boost::beast::http::verb::head, {{"Login"}}},
690 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
691 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
692 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
693 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
694 }
695
696 private:
697 /**
698 * Functions triggers appropriate requests on DBus
699 */
700 void doGet(crow::Response &res, const crow::Request &req,
701 const std::vector<std::string> &params) override
702 {
703 // Check if there is required param, truly entering this shall be
704 // impossible
705 if (params.size() != 2)
706 {
707 messages::internalError(res);
708
709 res.end();
710 return;
711 }
712 const std::string &name = params[0];
713 const std::string &resName = params[1];
714
715 auto asyncResp = std::make_shared<AsyncResp>(res);
716
717 if (name != "bmc")
718 {
719 messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
720
721 return;
722 }
723
724 crow::connections::systemBus->async_method_call(
725 [asyncResp, name, resName](const boost::system::error_code ec,
726 const GetObjectType &getObjectType) {
727 if (ec)
728 {
729 BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: "
730 << ec;
731 messages::internalError(asyncResp->res);
732
733 return;
734 }
735 std::string service = getObjectType.begin()->first;
736 BMCWEB_LOG_DEBUG << "GetObjectType: " << service;
737
738 getVmData(asyncResp, service, name, resName);
739 },
740 "xyz.openbmc_project.ObjectMapper",
741 "/xyz/openbmc_project/object_mapper",
742 "xyz.openbmc_project.ObjectMapper", "GetObject",
743 "/xyz/openbmc_project/VirtualMedia", std::array<const char *, 0>());
744 }
745};
746
747} // namespace redfish