blob: 1a94139abfb00732986cdff2a3abd8f276b1ad05 [file] [log] [blame]
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +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
James Feistb49ac872019-05-21 15:12:01 -070018#include "health.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080019#include "pcie.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080020#include "redfish_util.hpp"
21
Ed Tanous9712f8a2018-09-21 13:38:49 -070022#include <boost/container/flat_map.hpp>
23#include <node.hpp>
Andrew Geisslercb7e1e72019-02-19 13:05:38 -060024#include <utils/fw_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020025#include <utils/json_utils.hpp>
Ed Tanousabf2add2019-01-22 16:40:12 -080026#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020027
Ed Tanous1abe55e2018-09-05 08:30:59 -070028namespace redfish
29{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020030
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020031/**
Ed Tanous6c34de42018-08-29 13:37:36 -070032 * @brief Retrieves computer system properties over dbus
33 *
34 * @param[in] aResp Shared pointer for completing asynchronous calls
35 * @param[in] name Computer system name from request
36 *
37 * @return None.
38 */
Ed Tanous029573d2019-02-01 10:57:49 -080039void getComputerSystem(std::shared_ptr<AsyncResp> aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -070040{
Ed Tanous6c34de42018-08-29 13:37:36 -070041 BMCWEB_LOG_DEBUG << "Get available system components.";
42 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -080043 [aResp](
Ed Tanous6c34de42018-08-29 13:37:36 -070044 const boost::system::error_code ec,
45 const std::vector<std::pair<
46 std::string,
47 std::vector<std::pair<std::string, std::vector<std::string>>>>>
48 &subtree) {
49 if (ec)
50 {
51 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -070052 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -070053 return;
54 }
Ed Tanous6c34de42018-08-29 13:37:36 -070055 // Iterate over all retrieved ObjectPaths.
56 for (const std::pair<std::string,
57 std::vector<std::pair<
58 std::string, std::vector<std::string>>>>
59 &object : subtree)
60 {
61 const std::string &path = object.first;
62 BMCWEB_LOG_DEBUG << "Got path: " << path;
63 const std::vector<
64 std::pair<std::string, std::vector<std::string>>>
65 &connectionNames = object.second;
66 if (connectionNames.size() < 1)
67 {
68 continue;
69 }
Ed Tanous029573d2019-02-01 10:57:49 -080070
71 // This is not system, so check if it's cpu, dimm, UUID or
72 // BiosVer
73 for (const auto &connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -070074 {
Ed Tanous029573d2019-02-01 10:57:49 -080075 for (const auto &interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -070076 {
Ed Tanous029573d2019-02-01 10:57:49 -080077 if (interfaceName ==
78 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -070079 {
Ed Tanous029573d2019-02-01 10:57:49 -080080 BMCWEB_LOG_DEBUG
81 << "Found Dimm, now get its properties.";
82 crow::connections::systemBus->async_method_call(
83 [aResp](const boost::system::error_code ec,
Ed Tanous6c34de42018-08-29 13:37:36 -070084 const std::vector<
85 std::pair<std::string, VariantType>>
86 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -080087 if (ec)
88 {
89 BMCWEB_LOG_ERROR
90 << "DBUS response error " << ec;
91 messages::internalError(aResp->res);
92 return;
93 }
94 BMCWEB_LOG_DEBUG << "Got "
95 << properties.size()
96 << "Dimm properties.";
97 for (const std::pair<std::string,
98 VariantType>
99 &property : properties)
100 {
101 if (property.first == "MemorySizeInKb")
Ed Tanous6c34de42018-08-29 13:37:36 -0700102 {
Ed Tanous029573d2019-02-01 10:57:49 -0800103 const uint64_t *value =
104 sdbusplus::message::variant_ns::
105 get_if<uint64_t>(
106 &property.second);
107 if (value != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700108 {
Ed Tanous029573d2019-02-01 10:57:49 -0800109 aResp->res.jsonValue
110 ["TotalSystemMemoryGi"
111 "B"] +=
112 *value / (1024 * 1024);
113 aResp->res
114 .jsonValue["MemorySummary"]
115 ["Status"]
116 ["State"] =
117 "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700118 }
119 }
Ed Tanous029573d2019-02-01 10:57:49 -0800120 }
121 },
122 connection.first, path,
123 "org.freedesktop.DBus.Properties", "GetAll",
124 "xyz.openbmc_project.Inventory.Item.Dimm");
125 }
126 else if (interfaceName ==
127 "xyz.openbmc_project.Inventory.Item.Cpu")
128 {
129 BMCWEB_LOG_DEBUG
130 << "Found Cpu, now get its properties.";
131 crow::connections::systemBus->async_method_call(
132 [aResp](const boost::system::error_code ec,
Ed Tanous6c34de42018-08-29 13:37:36 -0700133 const std::vector<
134 std::pair<std::string, VariantType>>
135 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800136 if (ec)
137 {
138 BMCWEB_LOG_ERROR
139 << "DBUS response error " << ec;
140 messages::internalError(aResp->res);
141 return;
142 }
143 BMCWEB_LOG_DEBUG << "Got "
144 << properties.size()
145 << "Cpu properties.";
146 for (const auto &property : properties)
147 {
148 if (property.first == "ProcessorFamily")
Ed Tanous6c34de42018-08-29 13:37:36 -0700149 {
Ed Tanous029573d2019-02-01 10:57:49 -0800150 const std::string *value =
151 sdbusplus::message::variant_ns::
152 get_if<std::string>(
153 &property.second);
154 if (value != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700155 {
Ed Tanous029573d2019-02-01 10:57:49 -0800156 nlohmann::json &procSummary =
157 aResp->res.jsonValue
158 ["ProcessorSumm"
159 "ary"];
160 nlohmann::json &procCount =
161 procSummary["Count"];
Ed Tanous04a258f2018-10-15 08:00:41 -0700162
Ed Tanous029573d2019-02-01 10:57:49 -0800163 procCount =
164 procCount.get<int>() + 1;
165 procSummary["Status"]["State"] =
166 "Enabled";
167 procSummary["Model"] = *value;
Ed Tanous6c34de42018-08-29 13:37:36 -0700168 }
169 }
Ed Tanous029573d2019-02-01 10:57:49 -0800170 }
171 },
172 connection.first, path,
173 "org.freedesktop.DBus.Properties", "GetAll",
174 "xyz.openbmc_project.Inventory.Item.Cpu");
175 }
176 else if (interfaceName ==
177 "xyz.openbmc_project.Common.UUID")
178 {
179 BMCWEB_LOG_DEBUG
180 << "Found UUID, now get its properties.";
181 crow::connections::systemBus->async_method_call(
182 [aResp](const boost::system::error_code ec,
Ed Tanous6c34de42018-08-29 13:37:36 -0700183 const std::vector<
184 std::pair<std::string, VariantType>>
185 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800186 if (ec)
187 {
188 BMCWEB_LOG_DEBUG
189 << "DBUS response error " << ec;
190 messages::internalError(aResp->res);
191 return;
192 }
193 BMCWEB_LOG_DEBUG << "Got "
194 << properties.size()
195 << "UUID properties.";
196 for (const std::pair<std::string,
197 VariantType>
198 &property : properties)
199 {
Ed Tanous029573d2019-02-01 10:57:49 -0800200 if (property.first == "UUID")
201 {
202 const std::string *value =
203 sdbusplus::message::variant_ns::
204 get_if<std::string>(
205 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700206
Ed Tanous029573d2019-02-01 10:57:49 -0800207 if (value != nullptr)
208 {
209 std::string valueStr = *value;
210 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700211 {
Ed Tanous029573d2019-02-01 10:57:49 -0800212 valueStr.insert(8, 1, '-');
213 valueStr.insert(13, 1, '-');
214 valueStr.insert(18, 1, '-');
215 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700216 }
Ed Tanous029573d2019-02-01 10:57:49 -0800217 BMCWEB_LOG_DEBUG << "UUID = "
218 << valueStr;
219 aResp->res.jsonValue["UUID"] =
220 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700221 }
222 }
Ed Tanous029573d2019-02-01 10:57:49 -0800223 }
224 },
225 connection.first, path,
226 "org.freedesktop.DBus.Properties", "GetAll",
227 "xyz.openbmc_project.Common.UUID");
228 }
229 else if (interfaceName ==
230 "xyz.openbmc_project.Inventory.Item.System")
231 {
232 crow::connections::systemBus->async_method_call(
233 [aResp](const boost::system::error_code ec,
234 const std::vector<
235 std::pair<std::string, VariantType>>
236 &propertiesList) {
237 if (ec)
238 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700239 // doesn't have to include this
240 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800241 return;
242 }
243 BMCWEB_LOG_DEBUG << "Got "
244 << propertiesList.size()
245 << "properties for system";
246 for (const std::pair<std::string,
247 VariantType>
248 &property : propertiesList)
249 {
beccabroekfc5afcf2019-03-05 14:35:15 -0600250 const std::string &propertyName =
251 property.first;
252 if ((propertyName == "PartNumber") ||
253 (propertyName == "SerialNumber") ||
254 (propertyName == "Manufacturer") ||
255 (propertyName == "Model"))
Ed Tanous029573d2019-02-01 10:57:49 -0800256 {
beccabroekfc5afcf2019-03-05 14:35:15 -0600257 const std::string *value =
258 std::get_if<std::string>(
259 &property.second);
260 if (value != nullptr)
261 {
262 aResp->res
263 .jsonValue[propertyName] =
264 *value;
265 }
Ed Tanous029573d2019-02-01 10:57:49 -0800266 }
267 }
268 aResp->res.jsonValue["Name"] = "system";
269 aResp->res.jsonValue["Id"] =
270 aResp->res.jsonValue["SerialNumber"];
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600271 // Grab the bios version
272 fw_util::getActiveFwVersion(
273 aResp, fw_util::biosPurpose,
274 "BiosVersion");
Ed Tanous029573d2019-02-01 10:57:49 -0800275 },
276 connection.first, path,
277 "org.freedesktop.DBus.Properties", "GetAll",
278 "xyz.openbmc_project.Inventory.Decorator."
279 "Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700280
281 crow::connections::systemBus->async_method_call(
282 [aResp](
283 const boost::system::error_code ec,
284 const std::variant<std::string> &property) {
285 if (ec)
286 {
287 // doesn't have to include this
288 // interface
289 return;
290 }
291
292 const std::string *value =
293 std::get_if<std::string>(&property);
294 if (value != nullptr)
295 {
296 aResp->res.jsonValue["AssetTag"] =
297 *value;
298 }
299 },
300 connection.first, path,
301 "org.freedesktop.DBus.Properties", "Get",
302 "xyz.openbmc_project.Inventory.Decorator."
303 "AssetTag",
304 "AssetTag");
Ed Tanous6c34de42018-08-29 13:37:36 -0700305 }
306 }
307 }
308 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700309 },
310 "xyz.openbmc_project.ObjectMapper",
311 "/xyz/openbmc_project/object_mapper",
312 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700313 "/xyz/openbmc_project/inventory", int32_t(0),
314 std::array<const char *, 5>{
315 "xyz.openbmc_project.Inventory.Decorator.Asset",
316 "xyz.openbmc_project.Inventory.Item.Cpu",
317 "xyz.openbmc_project.Inventory.Item.Dimm",
318 "xyz.openbmc_project.Inventory.Item.System",
319 "xyz.openbmc_project.Common.UUID",
320 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700321}
322
323/**
324 * @brief Retrieves identify led group properties over dbus
325 *
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530326 * @param[in] aResp Shared pointer for generating response message.
Ed Tanous6c34de42018-08-29 13:37:36 -0700327 * @param[in] callback Callback for process retrieved data.
328 *
329 * @return None.
330 */
331template <typename CallbackFunc>
332void getLedGroupIdentify(std::shared_ptr<AsyncResp> aResp,
333 CallbackFunc &&callback)
334{
335 BMCWEB_LOG_DEBUG << "Get led groups";
336 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800337 [aResp,
Ed Tanous66173382018-08-15 18:20:59 -0700338 callback{std::move(callback)}](const boost::system::error_code &ec,
339 const ManagedObjectsType &resp) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700340 if (ec)
341 {
342 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700343 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700344 return;
345 }
346 BMCWEB_LOG_DEBUG << "Got " << resp.size() << "led group objects.";
347 for (const auto &objPath : resp)
348 {
349 const std::string &path = objPath.first;
350 if (path.rfind("enclosure_identify") != std::string::npos)
351 {
352 for (const auto &interface : objPath.second)
353 {
354 if (interface.first == "xyz.openbmc_project.Led.Group")
355 {
356 for (const auto &property : interface.second)
357 {
358 if (property.first == "Asserted")
359 {
360 const bool *asserted =
Ed Tanousabf2add2019-01-22 16:40:12 -0800361 std::get_if<bool>(&property.second);
Ed Tanous6c34de42018-08-29 13:37:36 -0700362 if (nullptr != asserted)
363 {
364 callback(*asserted, aResp);
365 }
366 else
367 {
368 callback(false, aResp);
369 }
370 }
371 }
372 }
373 }
374 }
375 }
376 },
377 "xyz.openbmc_project.LED.GroupManager",
378 "/xyz/openbmc_project/led/groups", "org.freedesktop.DBus.ObjectManager",
379 "GetManagedObjects");
380}
381
382template <typename CallbackFunc>
383void getLedIdentify(std::shared_ptr<AsyncResp> aResp, CallbackFunc &&callback)
384{
385 BMCWEB_LOG_DEBUG << "Get identify led properties";
386 crow::connections::systemBus->async_method_call(
Ed Tanous66173382018-08-15 18:20:59 -0700387 [aResp,
388 callback{std::move(callback)}](const boost::system::error_code ec,
389 const PropertiesType &properties) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700390 if (ec)
391 {
392 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700393 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700394 return;
395 }
396 BMCWEB_LOG_DEBUG << "Got " << properties.size()
397 << "led properties.";
398 std::string output;
399 for (const auto &property : properties)
400 {
401 if (property.first == "State")
402 {
403 const std::string *s =
Ed Tanousabf2add2019-01-22 16:40:12 -0800404 std::get_if<std::string>(&property.second);
Ed Tanous6c34de42018-08-29 13:37:36 -0700405 if (nullptr != s)
406 {
407 BMCWEB_LOG_DEBUG << "Identify Led State: " << *s;
408 const auto pos = s->rfind('.');
409 if (pos != std::string::npos)
410 {
411 auto led = s->substr(pos + 1);
412 for (const std::pair<const char *, const char *>
413 &p :
414 std::array<
415 std::pair<const char *, const char *>, 3>{
416 {{"On", "Lit"},
417 {"Blink", "Blinking"},
418 {"Off", "Off"}}})
419 {
420 if (led == p.first)
421 {
422 output = p.second;
423 }
424 }
425 }
426 }
427 }
428 }
429 callback(output, aResp);
430 },
431 "xyz.openbmc_project.LED.Controller.identify",
432 "/xyz/openbmc_project/led/physical/identify",
433 "org.freedesktop.DBus.Properties", "GetAll",
434 "xyz.openbmc_project.Led.Physical");
435}
Ed Tanous6c34de42018-08-29 13:37:36 -0700436/**
437 * @brief Retrieves host state properties over dbus
438 *
439 * @param[in] aResp Shared pointer for completing asynchronous calls.
440 *
441 * @return None.
442 */
443void getHostState(std::shared_ptr<AsyncResp> aResp)
444{
445 BMCWEB_LOG_DEBUG << "Get host information.";
446 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800447 [aResp](const boost::system::error_code ec,
448 const std::variant<std::string> &hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700449 if (ec)
450 {
451 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700452 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700453 return;
454 }
Ed Tanous66173382018-08-15 18:20:59 -0700455
Ed Tanousabf2add2019-01-22 16:40:12 -0800456 const std::string *s = std::get_if<std::string>(&hostState);
Ed Tanous66173382018-08-15 18:20:59 -0700457 BMCWEB_LOG_DEBUG << "Host state: " << *s;
458 if (s != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700459 {
Ed Tanous66173382018-08-15 18:20:59 -0700460 // Verify Host State
Andrew Geissler94732662019-01-08 19:32:16 -0800461 if (*s == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700462 {
Ed Tanous66173382018-08-15 18:20:59 -0700463 aResp->res.jsonValue["PowerState"] = "On";
464 aResp->res.jsonValue["Status"]["State"] = "Enabled";
465 }
466 else
467 {
468 aResp->res.jsonValue["PowerState"] = "Off";
469 aResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700470 }
471 }
472 },
473 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Ed Tanous66173382018-08-15 18:20:59 -0700474 "org.freedesktop.DBus.Properties", "Get",
475 "xyz.openbmc_project.State.Host", "CurrentHostState");
Ed Tanous6c34de42018-08-29 13:37:36 -0700476}
477
478/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530479 * @brief Traslates boot source DBUS property value to redfish.
480 *
481 * @param[in] dbusSource The boot source in DBUS speak.
482 *
483 * @return Returns as a string, the boot source in Redfish terms. If translation
484 * cannot be done, returns an empty string.
485 */
486static std::string dbusToRfBootSource(const std::string &dbusSource)
487{
488 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
489 {
490 return "None";
491 }
492 else if (dbusSource ==
493 "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
494 {
495 return "Hdd";
496 }
497 else if (dbusSource ==
Santosh Puranika71dc0b2019-05-23 20:10:49 +0530498 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530499 {
500 return "Cd";
501 }
502 else if (dbusSource ==
503 "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
504 {
505 return "Pxe";
506 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700507 else if (dbusSource ==
508 "xyz.openbmc_project.Control.Boot.Source.Sources.Removable")
509 {
510 return "Usb";
511 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530512 else
513 {
514 return "";
515 }
516}
517
518/**
519 * @brief Traslates boot mode DBUS property value to redfish.
520 *
521 * @param[in] dbusMode The boot mode in DBUS speak.
522 *
523 * @return Returns as a string, the boot mode in Redfish terms. If translation
524 * cannot be done, returns an empty string.
525 */
526static std::string dbusToRfBootMode(const std::string &dbusMode)
527{
528 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
529 {
530 return "None";
531 }
532 else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
533 {
534 return "Diags";
535 }
536 else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
537 {
538 return "BiosSetup";
539 }
540 else
541 {
542 return "";
543 }
544}
545
546/**
547 * @brief Traslates boot source from Redfish to DBUS property value.
548 *
549 * @param[in] rfSource The boot source in Redfish.
550 *
551 * @return Returns as a string, the boot source as expected by DBUS.
552 * If translation cannot be done, returns an empty string.
553 */
554static std::string rfToDbusBootSource(const std::string &rfSource)
555{
556 if (rfSource == "None")
557 {
558 return "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
559 }
560 else if (rfSource == "Hdd")
561 {
562 return "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
563 }
564 else if (rfSource == "Cd")
565 {
Santosh Puranika71dc0b2019-05-23 20:10:49 +0530566 return "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530567 }
568 else if (rfSource == "Pxe")
569 {
570 return "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
571 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700572 else if (rfSource == "Usb")
573 {
574 return "xyz.openbmc_project.Control.Boot.Source.Sources.Removable";
575 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530576 else
577 {
578 return "";
579 }
580}
581
582/**
583 * @brief Traslates boot mode from Redfish to DBUS property value.
584 *
585 * @param[in] rfMode The boot mode in Redfish.
586 *
587 * @return Returns as a string, the boot mode as expected by DBUS.
588 * If translation cannot be done, returns an empty string.
589 */
590static std::string rfToDbusBootMode(const std::string &rfMode)
591{
592 if (rfMode == "None")
593 {
594 return "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
595 }
596 else if (rfMode == "Diags")
597 {
598 return "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
599 }
600 else if (rfMode == "BiosSetup")
601 {
602 return "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
603 }
604 else
605 {
606 return "";
607 }
608}
609
610/**
611 * @brief Retrieves boot mode over DBUS and fills out the response
612 *
613 * @param[in] aResp Shared pointer for generating response message.
614 * @param[in] bootDbusObj The dbus object to query for boot properties.
615 *
616 * @return None.
617 */
618static void getBootMode(std::shared_ptr<AsyncResp> aResp,
619 std::string bootDbusObj)
620{
621 crow::connections::systemBus->async_method_call(
622 [aResp](const boost::system::error_code ec,
623 const std::variant<std::string> &bootMode) {
624 if (ec)
625 {
626 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
627 messages::internalError(aResp->res);
628 return;
629 }
630
631 const std::string *bootModeStr =
632 std::get_if<std::string>(&bootMode);
633
634 if (!bootModeStr)
635 {
636 messages::internalError(aResp->res);
637 return;
638 }
639
640 BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
641
642 // TODO (Santosh): Do we need to support override mode?
643 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = "Legacy";
644 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
645 "AllowableValues"] = {
646 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup"};
647
648 if (*bootModeStr !=
649 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
650 {
651 auto rfMode = dbusToRfBootMode(*bootModeStr);
652 if (!rfMode.empty())
653 {
654 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
655 rfMode;
656 }
657 }
658
659 // If the BootSourceOverrideTarget is still "None" at the end,
660 // reset the BootSourceOverrideEnabled to indicate that
661 // overrides are disabled
662 if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] ==
663 "None")
664 {
665 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
666 "Disabled";
667 }
668 },
669 "xyz.openbmc_project.Settings", bootDbusObj,
670 "org.freedesktop.DBus.Properties", "Get",
671 "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
672}
673
674/**
675 * @brief Retrieves boot source over DBUS
676 *
677 * @param[in] aResp Shared pointer for generating response message.
678 * @param[in] oneTimeEnable Boolean to indicate boot properties are one-time.
679 *
680 * @return None.
681 */
682static void getBootSource(std::shared_ptr<AsyncResp> aResp, bool oneTimeEnabled)
683{
684 std::string bootDbusObj =
685 oneTimeEnabled ? "/xyz/openbmc_project/control/host0/boot/one_time"
686 : "/xyz/openbmc_project/control/host0/boot";
687
688 BMCWEB_LOG_DEBUG << "Is one time: " << oneTimeEnabled;
689 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
690 (oneTimeEnabled) ? "Once" : "Continuous";
691
692 crow::connections::systemBus->async_method_call(
693 [aResp, bootDbusObj](const boost::system::error_code ec,
694 const std::variant<std::string> &bootSource) {
695 if (ec)
696 {
697 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
698 messages::internalError(aResp->res);
699 return;
700 }
701
702 const std::string *bootSourceStr =
703 std::get_if<std::string>(&bootSource);
704
705 if (!bootSourceStr)
706 {
707 messages::internalError(aResp->res);
708 return;
709 }
710 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
711
712 auto rfSource = dbusToRfBootSource(*bootSourceStr);
713 if (!rfSource.empty())
714 {
715 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
716 rfSource;
717 }
718 },
719 "xyz.openbmc_project.Settings", bootDbusObj,
720 "org.freedesktop.DBus.Properties", "Get",
721 "xyz.openbmc_project.Control.Boot.Source", "BootSource");
722 getBootMode(std::move(aResp), std::move(bootDbusObj));
723}
724
725/**
726 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
727 * get boot source and boot mode.
728 *
729 * @param[in] aResp Shared pointer for generating response message.
730 *
731 * @return None.
732 */
733static void getBootProperties(std::shared_ptr<AsyncResp> aResp)
734{
735 BMCWEB_LOG_DEBUG << "Get boot information.";
736
737 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800738 [aResp](const boost::system::error_code ec,
739 const sdbusplus::message::variant<bool> &oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530740 if (ec)
741 {
742 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
743 messages::internalError(aResp->res);
744 return;
745 }
746
747 const bool *oneTimePtr = std::get_if<bool>(&oneTime);
748
749 if (!oneTimePtr)
750 {
751 messages::internalError(aResp->res);
752 return;
753 }
754 getBootSource(aResp, *oneTimePtr);
755 },
756 "xyz.openbmc_project.Settings",
757 "/xyz/openbmc_project/control/host0/boot/one_time",
758 "org.freedesktop.DBus.Properties", "Get",
759 "xyz.openbmc_project.Object.Enable", "Enabled");
760}
761
762/**
763 * @brief Sets boot properties into DBUS object(s).
764 *
765 * @param[in] aResp Shared pointer for generating response message.
766 * @param[in] oneTimeEnabled Is "one-time" setting already enabled.
767 * @param[in] bootSource The boot source to set.
768 * @param[in] bootEnable The source override "enable" to set.
769 *
770 * @return None.
771 */
772static void setBootModeOrSource(std::shared_ptr<AsyncResp> aResp,
773 bool oneTimeEnabled,
774 std::optional<std::string> bootSource,
775 std::optional<std::string> bootEnable)
776{
777 if (bootEnable && (bootEnable != "Once") && (bootEnable != "Continuous") &&
778 (bootEnable != "Disabled"))
779 {
780 BMCWEB_LOG_DEBUG << "Unsupported value for BootSourceOverrideEnabled: "
781 << *bootEnable;
782 messages::propertyValueNotInList(aResp->res, *bootEnable,
783 "BootSourceOverrideEnabled");
784 return;
785 }
786
787 bool oneTimeSetting = oneTimeEnabled;
788 // Validate incoming parameters
789 if (bootEnable)
790 {
791 if (*bootEnable == "Once")
792 {
793 oneTimeSetting = true;
794 }
795 else if (*bootEnable == "Continuous")
796 {
797 oneTimeSetting = false;
798 }
799 else if (*bootEnable == "Disabled")
800 {
801 oneTimeSetting = false;
802 }
803 else
804 {
805
806 BMCWEB_LOG_DEBUG << "Unsupported value for "
807 "BootSourceOverrideEnabled: "
808 << *bootEnable;
809 messages::propertyValueNotInList(aResp->res, *bootEnable,
810 "BootSourceOverrideEnabled");
811 return;
812 }
813 }
814 std::string bootSourceStr;
815 std::string bootModeStr;
816 if (bootSource)
817 {
818 bootSourceStr = rfToDbusBootSource(*bootSource);
819 bootModeStr = rfToDbusBootMode(*bootSource);
820
821 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
822 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
823
824 if (bootSourceStr.empty() && bootModeStr.empty())
825 {
826 BMCWEB_LOG_DEBUG << "Invalid property value for "
827 "BootSourceOverrideTarget: "
828 << *bootSource;
829 messages::propertyValueNotInList(aResp->res, *bootSource,
830 "BootSourceTargetOverride");
831 return;
832 }
833 }
834 const char *bootObj =
835 oneTimeSetting ? "/xyz/openbmc_project/control/host0/boot/one_time"
836 : "/xyz/openbmc_project/control/host0/boot";
837 // Figure out what properties to set
838 if (bootEnable && (*bootEnable == "Disabled"))
839 {
840 BMCWEB_LOG_DEBUG << "Boot source override will be disabled";
841 // Request to only turn OFF/ON enabled, if turning enabled OFF, need
842 // to reset the source and mode too. If turning it ON, we only need
843 // to set the enabled property
844 bootSourceStr =
845 "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
846 bootModeStr = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
847 }
848 else if (bootSource)
849 {
850 // Source target specified
851 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
852 // Figure out which DBUS interface and property to use
853 bootSourceStr = rfToDbusBootSource(*bootSource);
854 bootModeStr = rfToDbusBootMode(*bootSource);
855
856 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
857 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
858
859 if (bootSourceStr.empty() && bootModeStr.empty())
860 {
861 BMCWEB_LOG_DEBUG << "Invalid property value for "
862 "BootSourceOverrideTarget: "
863 << *bootSource;
864 messages::propertyValueNotInList(aResp->res, *bootSource,
865 "BootSourceTargetOverride");
866 return;
867 }
868
869 if (!bootSourceStr.empty())
870 {
871 // If setting to anything other than default, also reset boot
872 // mode property
873 if (bootSourceStr !=
874 "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
875 {
876 bootModeStr =
877 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
878 }
879 }
880 else // if (!bootModeStr.empty())
881 {
882 // If setting to anything other than default, also reset boot
883 // source property
884 if (bootModeStr !=
885 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
886 {
887 bootSourceStr =
888 "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
889 }
890 }
891 }
892 if (!bootSourceStr.empty())
893 {
894 crow::connections::systemBus->async_method_call(
895 [aResp](const boost::system::error_code ec) {
896 if (ec)
897 {
898 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
899 messages::internalError(aResp->res);
900 return;
901 }
902 BMCWEB_LOG_DEBUG << "Boot source update done.";
903 },
904 "xyz.openbmc_project.Settings", bootObj,
905 "org.freedesktop.DBus.Properties", "Set",
906 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
907 std::variant<std::string>(bootSourceStr));
908 }
909 if (!bootModeStr.empty())
910 {
911 crow::connections::systemBus->async_method_call(
912 [aResp](const boost::system::error_code ec) {
913 if (ec)
914 {
915 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
916 messages::internalError(aResp->res);
917 return;
918 }
919 BMCWEB_LOG_DEBUG << "Boot mode update done.";
920 },
921 "xyz.openbmc_project.Settings", bootObj,
922 "org.freedesktop.DBus.Properties", "Set",
923 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
924 std::variant<std::string>(bootModeStr));
925 }
926 crow::connections::systemBus->async_method_call(
927 [aResp{std::move(aResp)}](const boost::system::error_code ec) {
928 if (ec)
929 {
930 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
931 messages::internalError(aResp->res);
932 return;
933 }
934 BMCWEB_LOG_DEBUG << "Boot enable update done.";
935 },
936 "xyz.openbmc_project.Settings",
937 "/xyz/openbmc_project/control/host0/boot/one_time",
938 "org.freedesktop.DBus.Properties", "Set",
939 "xyz.openbmc_project.Object.Enable", "Enabled",
940 std::variant<bool>(oneTimeSetting));
941}
942
943/**
944 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
945 * set boot source/boot mode properties.
946 *
947 * @param[in] aResp Shared pointer for generating response message.
948 * @param[in] bootSource The boot source from incoming RF request.
949 * @param[in] bootEnable The boot override enable from incoming RF request.
950 *
951 * @return None.
952 */
953static void setBootProperties(std::shared_ptr<AsyncResp> aResp,
954 std::optional<std::string> bootSource,
955 std::optional<std::string> bootEnable)
956{
957 BMCWEB_LOG_DEBUG << "Set boot information.";
958
959 crow::connections::systemBus->async_method_call(
960 [aResp{std::move(aResp)}, bootSource{std::move(bootSource)},
961 bootEnable{std::move(bootEnable)}](
962 const boost::system::error_code ec,
963 const sdbusplus::message::variant<bool> &oneTime) {
964 if (ec)
965 {
966 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
967 messages::internalError(aResp->res);
968 return;
969 }
970
971 const bool *oneTimePtr = std::get_if<bool>(&oneTime);
972
973 if (!oneTimePtr)
974 {
975 messages::internalError(aResp->res);
976 return;
977 }
978
979 BMCWEB_LOG_DEBUG << "Got one time: " << *oneTimePtr;
980
981 setBootModeOrSource(aResp, *oneTimePtr, std::move(bootSource),
982 std::move(bootEnable));
983 },
984 "xyz.openbmc_project.Settings",
985 "/xyz/openbmc_project/control/host0/boot/one_time",
986 "org.freedesktop.DBus.Properties", "Get",
987 "xyz.openbmc_project.Object.Enable", "Enabled");
988}
989
990/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200991 * SystemsCollection derived class for delivering ComputerSystems Collection
992 * Schema
993 */
Ed Tanous1abe55e2018-09-05 08:30:59 -0700994class SystemsCollection : public Node
995{
996 public:
997 SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/")
998 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700999 entityPrivileges = {
1000 {boost::beast::http::verb::get, {{"Login"}}},
1001 {boost::beast::http::verb::head, {{"Login"}}},
1002 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1003 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1004 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1005 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1006 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001007
Ed Tanous1abe55e2018-09-05 08:30:59 -07001008 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -07001009 void doGet(crow::Response &res, const crow::Request &req,
1010 const std::vector<std::string> &params) override
1011 {
Ed Tanous0f74e642018-11-12 15:17:05 -08001012 res.jsonValue["@odata.type"] =
1013 "#ComputerSystemCollection.ComputerSystemCollection";
1014 res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
1015 res.jsonValue["@odata.context"] =
1016 "/redfish/v1/"
1017 "$metadata#ComputerSystemCollection.ComputerSystemCollection";
1018 res.jsonValue["Name"] = "Computer System Collection";
Ed Tanous029573d2019-02-01 10:57:49 -08001019 res.jsonValue["Members"] = {
1020 {{"@odata.id", "/redfish/v1/Systems/system"}}};
1021 res.jsonValue["Members@odata.count"] = 1;
1022 res.end();
Ed Tanous1abe55e2018-09-05 08:30:59 -07001023 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001024};
1025
1026/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07001027 * SystemActionsReset class supports handle POST method for Reset action.
1028 * The class retrieves and sends data directly to D-Bus.
1029 */
1030class SystemActionsReset : public Node
1031{
1032 public:
1033 SystemActionsReset(CrowApp &app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001034 Node(app, "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanouscc340dd2018-08-29 13:43:38 -07001035 {
1036 entityPrivileges = {
1037 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1038 }
1039
1040 private:
1041 /**
1042 * Function handles POST method request.
1043 * Analyzes POST body message before sends Reset request data to D-Bus.
1044 */
1045 void doPost(crow::Response &res, const crow::Request &req,
1046 const std::vector<std::string> &params) override
1047 {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001048 auto asyncResp = std::make_shared<AsyncResp>(res);
1049
1050 std::string resetType;
1051 if (!json_util::readJson(req, res, "ResetType", resetType))
Ed Tanouscc340dd2018-08-29 13:43:38 -07001052 {
1053 return;
1054 }
1055
Jason M. Billsd22c8392019-06-03 13:59:03 -07001056 // Get the command and host vs. chassis
Ed Tanous9712f8a2018-09-21 13:38:49 -07001057 std::string command;
Jason M. Billsd22c8392019-06-03 13:59:03 -07001058 bool hostCommand;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001059 if (resetType == "On")
1060 {
1061 command = "xyz.openbmc_project.State.Host.Transition.On";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001062 hostCommand = true;
1063 }
1064 else if (resetType == "ForceOff")
1065 {
1066 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
1067 hostCommand = false;
1068 }
1069 else if (resetType == "ForceOn")
1070 {
1071 command = "xyz.openbmc_project.State.Host.Transition.On";
1072 hostCommand = true;
1073 }
1074 else if (resetType == "ForceRestart")
1075 {
1076 command = "xyz.openbmc_project.State.Chassis.Transition.Reset";
1077 hostCommand = false;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001078 }
1079 else if (resetType == "GracefulShutdown")
1080 {
1081 command = "xyz.openbmc_project.State.Host.Transition.Off";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001082 hostCommand = true;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001083 }
1084 else if (resetType == "GracefulRestart")
1085 {
1086 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001087 hostCommand = true;
1088 }
1089 else if (resetType == "PowerCycle")
1090 {
1091 command = "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
1092 hostCommand = false;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001093 }
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001094 else if (resetType == "Nmi")
1095 {
1096 doNMI(asyncResp);
1097 return;
1098 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001099 else
1100 {
Jason M. Billsf12894f2018-10-09 12:45:45 -07001101 messages::actionParameterUnknown(res, "Reset", resetType);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001102 return;
1103 }
1104
Jason M. Billsd22c8392019-06-03 13:59:03 -07001105 if (hostCommand)
1106 {
1107 crow::connections::systemBus->async_method_call(
1108 [asyncResp, resetType](const boost::system::error_code ec) {
1109 if (ec)
1110 {
1111 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1112 if (ec.value() == boost::asio::error::invalid_argument)
1113 {
1114 messages::actionParameterNotSupported(
1115 asyncResp->res, resetType, "Reset");
1116 }
1117 else
1118 {
1119 messages::internalError(asyncResp->res);
1120 }
1121 return;
1122 }
1123 messages::success(asyncResp->res);
1124 },
1125 "xyz.openbmc_project.State.Host",
1126 "/xyz/openbmc_project/state/host0",
1127 "org.freedesktop.DBus.Properties", "Set",
1128 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
1129 std::variant<std::string>{command});
1130 }
1131 else
1132 {
1133 crow::connections::systemBus->async_method_call(
1134 [asyncResp, resetType](const boost::system::error_code ec) {
1135 if (ec)
1136 {
1137 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1138 if (ec.value() == boost::asio::error::invalid_argument)
1139 {
1140 messages::actionParameterNotSupported(
1141 asyncResp->res, resetType, "Reset");
1142 }
1143 else
1144 {
1145 messages::internalError(asyncResp->res);
1146 }
1147 return;
1148 }
1149 messages::success(asyncResp->res);
1150 },
1151 "xyz.openbmc_project.State.Chassis",
1152 "/xyz/openbmc_project/state/chassis0",
1153 "org.freedesktop.DBus.Properties", "Set",
1154 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
1155 std::variant<std::string>{command});
1156 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07001157 }
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001158 /**
1159 * Function transceives data with dbus directly.
1160 */
1161 void doNMI(const std::shared_ptr<AsyncResp> &asyncResp)
1162 {
1163 constexpr char const *serviceName =
1164 "xyz.openbmc_project.Control.Host.NMI";
1165 constexpr char const *objectPath =
1166 "/xyz/openbmc_project/control/host0/nmi";
1167 constexpr char const *interfaceName =
1168 "xyz.openbmc_project.Control.Host.NMI";
1169 constexpr char const *method = "NMI";
1170
1171 crow::connections::systemBus->async_method_call(
1172 [asyncResp](const boost::system::error_code ec) {
1173 if (ec)
1174 {
1175 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
1176 messages::internalError(asyncResp->res);
1177 return;
1178 }
1179 messages::success(asyncResp->res);
1180 },
1181 serviceName, objectPath, interfaceName, method);
1182 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07001183};
1184
1185/**
Ed Tanous66173382018-08-15 18:20:59 -07001186 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001187 */
Ed Tanous1abe55e2018-09-05 08:30:59 -07001188class Systems : public Node
1189{
1190 public:
1191 /*
1192 * Default Constructor
1193 */
Ed Tanous029573d2019-02-01 10:57:49 -08001194 Systems(CrowApp &app) : Node(app, "/redfish/v1/Systems/system/")
Ed Tanous1abe55e2018-09-05 08:30:59 -07001195 {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001196 entityPrivileges = {
1197 {boost::beast::http::verb::get, {{"Login"}}},
1198 {boost::beast::http::verb::head, {{"Login"}}},
1199 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1200 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1201 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1202 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001203 }
1204
Ed Tanous1abe55e2018-09-05 08:30:59 -07001205 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -07001206 /**
1207 * Functions triggers appropriate requests on DBus
1208 */
1209 void doGet(crow::Response &res, const crow::Request &req,
1210 const std::vector<std::string> &params) override
1211 {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301212 res.jsonValue["@odata.type"] = "#ComputerSystem.v1_6_0.ComputerSystem";
Ed Tanous0f74e642018-11-12 15:17:05 -08001213 res.jsonValue["@odata.context"] =
1214 "/redfish/v1/$metadata#ComputerSystem.ComputerSystem";
Ed Tanous029573d2019-02-01 10:57:49 -08001215 res.jsonValue["Name"] = "Computer System";
1216 res.jsonValue["Id"] = "system";
Ed Tanous0f74e642018-11-12 15:17:05 -08001217 res.jsonValue["SystemType"] = "Physical";
1218 res.jsonValue["Description"] = "Computer System";
Ed Tanous0f74e642018-11-12 15:17:05 -08001219 res.jsonValue["ProcessorSummary"]["Count"] = 0;
1220 res.jsonValue["ProcessorSummary"]["Status"]["State"] = "Disabled";
1221 res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] = int(0);
1222 res.jsonValue["MemorySummary"]["Status"]["State"] = "Disabled";
Ed Tanous029573d2019-02-01 10:57:49 -08001223 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07001224
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001225 res.jsonValue["Processors"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001226 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001227 res.jsonValue["Memory"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001228 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
1229
Ed Tanouscc340dd2018-08-29 13:43:38 -07001230 // TODO Need to support ForceRestart.
1231 res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
1232 {"target",
Ed Tanous029573d2019-02-01 10:57:49 -08001233 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
Ed Tanouscc340dd2018-08-29 13:43:38 -07001234 {"ResetType@Redfish.AllowableValues",
Jason M. Billsd22c8392019-06-03 13:59:03 -07001235 {"On", "ForceOff", "ForceOn", "ForceRestart", "GracefulRestart",
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001236 "GracefulShutdown", "PowerCycle", "Nmi"}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001237
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001238 res.jsonValue["LogServices"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001239 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001240
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001241 res.jsonValue["Links"]["ManagedBy"] = {
1242 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
1243
1244 res.jsonValue["Status"] = {
1245 {"Health", "OK"},
1246 {"State", "Enabled"},
1247 };
Ed Tanousa0803ef2018-08-29 13:29:23 -07001248 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001249
James Feistb49ac872019-05-21 15:12:01 -07001250 constexpr const std::array<const char *, 2> inventoryForSystems = {
1251 "xyz.openbmc_project.Inventory.Item.Dimm",
1252 "xyz.openbmc_project.Inventory.Item.Cpu"};
1253
1254 auto health = std::make_shared<HealthPopulate>(asyncResp);
1255 crow::connections::systemBus->async_method_call(
1256 [health](const boost::system::error_code ec,
1257 std::vector<std::string> &resp) {
1258 if (ec)
1259 {
1260 // no inventory
1261 return;
1262 }
1263
1264 health->inventory = std::move(resp);
1265 },
1266 "xyz.openbmc_project.ObjectMapper",
1267 "/xyz/openbmc_project/object_mapper",
1268 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
1269 int32_t(0), inventoryForSystems);
1270
1271 health->populate();
1272
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001273 getMainChassisId(asyncResp, [](const std::string &chassisId,
1274 std::shared_ptr<AsyncResp> aRsp) {
1275 aRsp->res.jsonValue["Links"]["Chassis"] = {
1276 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
1277 });
Ed Tanous6c34de42018-08-29 13:37:36 -07001278 getLedGroupIdentify(
Ed Tanousa0803ef2018-08-29 13:29:23 -07001279 asyncResp,
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001280 [](const bool &asserted, const std::shared_ptr<AsyncResp> aRsp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001281 if (asserted)
1282 {
1283 // If led group is asserted, then another call is needed to
1284 // get led status
Ed Tanous6c34de42018-08-29 13:37:36 -07001285 getLedIdentify(
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001286 aRsp, [](const std::string &ledStatus,
1287 const std::shared_ptr<AsyncResp> aRsp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001288 if (!ledStatus.empty())
1289 {
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001290 aRsp->res.jsonValue["IndicatorLED"] = ledStatus;
Ed Tanous1abe55e2018-09-05 08:30:59 -07001291 }
1292 });
1293 }
1294 else
1295 {
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001296 aRsp->res.jsonValue["IndicatorLED"] = "Off";
Ed Tanous1abe55e2018-09-05 08:30:59 -07001297 }
1298 });
Ed Tanous029573d2019-02-01 10:57:49 -08001299 getComputerSystem(asyncResp);
Ed Tanous6c34de42018-08-29 13:37:36 -07001300 getHostState(asyncResp);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301301 getBootProperties(asyncResp);
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -08001302 getPCIeDeviceList(asyncResp);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001303 }
1304
Ed Tanous1abe55e2018-09-05 08:30:59 -07001305 void doPatch(crow::Response &res, const crow::Request &req,
1306 const std::vector<std::string> &params) override
1307 {
Santosh Puranikcde19e52019-02-20 00:10:56 +05301308 std::optional<std::string> indicatorLed;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301309 std::optional<nlohmann::json> bootProps;
1310 if (!json_util::readJson(req, res, "IndicatorLED", indicatorLed, "Boot",
1311 bootProps))
Ed Tanous66173382018-08-15 18:20:59 -07001312 {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001313 return;
1314 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301315
Ed Tanous029573d2019-02-01 10:57:49 -08001316 auto asyncResp = std::make_shared<AsyncResp>(res);
Jennifer Leed573bb22019-04-10 13:49:51 -07001317 asyncResp->res.result(boost::beast::http::status::no_content);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301318
1319 if (bootProps)
1320 {
1321 std::optional<std::string> bootSource;
1322 std::optional<std::string> bootEnable;
1323
1324 if (!json_util::readJson(*bootProps, asyncResp->res,
1325 "BootSourceOverrideTarget", bootSource,
1326 "BootSourceOverrideEnabled", bootEnable))
1327 {
1328 return;
1329 }
1330 setBootProperties(asyncResp, std::move(bootSource),
1331 std::move(bootEnable));
1332 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001333 if (indicatorLed)
1334 {
1335 std::string dbusLedState;
Jennifer Leed573bb22019-04-10 13:49:51 -07001336 if (*indicatorLed == "Lit")
Ed Tanous66173382018-08-15 18:20:59 -07001337 {
Jennifer Leed573bb22019-04-10 13:49:51 -07001338 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.On";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001339 }
Gunnar Mills5c6221a2019-02-22 11:24:29 -06001340 else if (*indicatorLed == "Blinking")
Ed Tanous9712f8a2018-09-21 13:38:49 -07001341 {
Gunnar Mills5c6221a2019-02-22 11:24:29 -06001342 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.Blink";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001343 }
1344 else if (*indicatorLed == "Off")
1345 {
1346 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.Off";
Ed Tanous66173382018-08-15 18:20:59 -07001347 }
1348 else
1349 {
Jason M. Billsa08b46c2018-11-06 15:01:08 -08001350 messages::propertyValueNotInList(res, *indicatorLed,
1351 "IndicatorLED");
Ed Tanous66173382018-08-15 18:20:59 -07001352 return;
1353 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001354
Ed Tanous9712f8a2018-09-21 13:38:49 -07001355 // Update led group
1356 BMCWEB_LOG_DEBUG << "Update led group.";
1357 crow::connections::systemBus->async_method_call(
Santosh Puranikcde19e52019-02-20 00:10:56 +05301358 [asyncResp](const boost::system::error_code ec) {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001359 if (ec)
1360 {
1361 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -07001362 messages::internalError(asyncResp->res);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001363 return;
1364 }
1365 BMCWEB_LOG_DEBUG << "Led group update done.";
1366 },
1367 "xyz.openbmc_project.LED.GroupManager",
1368 "/xyz/openbmc_project/led/groups/enclosure_identify",
1369 "org.freedesktop.DBus.Properties", "Set",
1370 "xyz.openbmc_project.Led.Group", "Asserted",
Ed Tanousabf2add2019-01-22 16:40:12 -08001371 std::variant<bool>(
Ed Tanous9712f8a2018-09-21 13:38:49 -07001372 (dbusLedState ==
1373 "xyz.openbmc_project.Led.Physical.Action.Off"
1374 ? false
1375 : true)));
1376 // Update identify led status
1377 BMCWEB_LOG_DEBUG << "Update led SoftwareInventoryCollection.";
1378 crow::connections::systemBus->async_method_call(
1379 [asyncResp{std::move(asyncResp)},
1380 indicatorLed{std::move(*indicatorLed)}](
1381 const boost::system::error_code ec) {
1382 if (ec)
1383 {
1384 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -07001385 messages::internalError(asyncResp->res);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001386 return;
1387 }
1388 BMCWEB_LOG_DEBUG << "Led state update done.";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001389 },
1390 "xyz.openbmc_project.LED.Controller.identify",
1391 "/xyz/openbmc_project/led/physical/identify",
1392 "org.freedesktop.DBus.Properties", "Set",
1393 "xyz.openbmc_project.Led.Physical", "State",
Ed Tanousabf2add2019-01-22 16:40:12 -08001394 std::variant<std::string>(dbusLedState));
Ed Tanous1abe55e2018-09-05 08:30:59 -07001395 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001396 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001397};
Ed Tanous1abe55e2018-09-05 08:30:59 -07001398} // namespace redfish