blob: 338bdc3e4b6254e230d2b9113787e5c62689a142 [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"
James Feist1c8fba92019-12-20 15:12:07 -080019#include "led.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080020#include "pcie.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080021#include "redfish_util.hpp"
22
Ed Tanous9712f8a2018-09-21 13:38:49 -070023#include <boost/container/flat_map.hpp>
24#include <node.hpp>
Andrew Geisslercb7e1e72019-02-19 13:05:38 -060025#include <utils/fw_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020026#include <utils/json_utils.hpp>
Ed Tanousabf2add2019-01-22 16:40:12 -080027#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020028
Ed Tanous1abe55e2018-09-05 08:30:59 -070029namespace redfish
30{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020031
Alpana Kumari9d3ae102019-04-12 06:49:32 -050032/**
33 * @brief Updates the Functional State of DIMMs
34 *
35 * @param[in] aResp Shared pointer for completing asynchronous calls
36 * @param[in] dimmState Dimm's Functional state, true/false
37 *
38 * @return None.
39 */
40void updateDimmProperties(std::shared_ptr<AsyncResp> aResp,
41 const std::variant<bool> &dimmState)
42{
43 const bool *isDimmFunctional = std::get_if<bool>(&dimmState);
44 if (isDimmFunctional == nullptr)
45 {
46 messages::internalError(aResp->res);
47 return;
48 }
Gunnar Mills698654b2019-10-16 13:17:37 -050049 BMCWEB_LOG_DEBUG << "Dimm Functional: " << *isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050050
51 // Set it as Enabled if atleast one DIMM is functional
52 // Update STATE only if previous State was DISABLED and current Dimm is
53 // ENABLED.
54 nlohmann::json &prevMemSummary =
55 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
56 if (prevMemSummary == "Disabled")
57 {
58 if (*isDimmFunctional == true)
59 {
60 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
61 "Enabled";
62 }
63 }
64}
65
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050066/*
67 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
68 *
69 * @param[in] aResp Shared pointer for completing asynchronous calls
70 * @param[in] cpuPresenceState CPU present or not
71 *
72 * @return None.
73 */
74void modifyCpuPresenceState(std::shared_ptr<AsyncResp> aResp,
75 const std::variant<bool> &cpuPresenceState)
76{
77 const bool *isCpuPresent = std::get_if<bool>(&cpuPresenceState);
78
79 if (isCpuPresent == nullptr)
80 {
81 messages::internalError(aResp->res);
82 return;
83 }
Gunnar Mills698654b2019-10-16 13:17:37 -050084 BMCWEB_LOG_DEBUG << "Cpu Present: " << *isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050085
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050086 if (*isCpuPresent == true)
87 {
James Feistb4b95952019-12-05 15:01:55 -080088 nlohmann::json &procCount =
89 aResp->res.jsonValue["ProcessorSummary"]["Count"];
90 auto procCountPtr =
91 procCount.get_ptr<nlohmann::json::number_integer_t *>();
92 if (procCountPtr != nullptr)
93 {
94 // shouldn't be possible to be nullptr
95 *procCountPtr += 1;
96 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050097 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050098}
99
100/*
101 * @brief Update "ProcessorSummary" "Status" "State" based on
102 * CPU Functional State
103 *
104 * @param[in] aResp Shared pointer for completing asynchronous calls
105 * @param[in] cpuFunctionalState is CPU functional true/false
106 *
107 * @return None.
108 */
109void modifyCpuFunctionalState(std::shared_ptr<AsyncResp> aResp,
110 const std::variant<bool> &cpuFunctionalState)
111{
112 const bool *isCpuFunctional = std::get_if<bool>(&cpuFunctionalState);
113
114 if (isCpuFunctional == nullptr)
115 {
116 messages::internalError(aResp->res);
117 return;
118 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500119 BMCWEB_LOG_DEBUG << "Cpu Functional: " << *isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500120
121 nlohmann::json &prevProcState =
122 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
123
124 // Set it as Enabled if atleast one CPU is functional
125 // Update STATE only if previous State was Non_Functional and current CPU is
126 // Functional.
127 if (prevProcState == "Disabled")
128 {
129 if (*isCpuFunctional == true)
130 {
131 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
132 "Enabled";
133 }
134 }
135}
136
137/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700138 * @brief Retrieves computer system properties over dbus
139 *
140 * @param[in] aResp Shared pointer for completing asynchronous calls
141 * @param[in] name Computer system name from request
142 *
143 * @return None.
144 */
James Feist5bc2dc82019-10-22 14:33:16 -0700145void getComputerSystem(std::shared_ptr<AsyncResp> aResp,
146 std::shared_ptr<HealthPopulate> systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700147{
Ed Tanous6c34de42018-08-29 13:37:36 -0700148 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500149
Ed Tanous6c34de42018-08-29 13:37:36 -0700150 crow::connections::systemBus->async_method_call(
James Feist5bc2dc82019-10-22 14:33:16 -0700151 [aResp, systemHealth](
Ed Tanous6c34de42018-08-29 13:37:36 -0700152 const boost::system::error_code ec,
153 const std::vector<std::pair<
154 std::string,
155 std::vector<std::pair<std::string, std::vector<std::string>>>>>
156 &subtree) {
157 if (ec)
158 {
159 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700160 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700161 return;
162 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700163 // Iterate over all retrieved ObjectPaths.
164 for (const std::pair<std::string,
165 std::vector<std::pair<
166 std::string, std::vector<std::string>>>>
167 &object : subtree)
168 {
169 const std::string &path = object.first;
170 BMCWEB_LOG_DEBUG << "Got path: " << path;
171 const std::vector<
172 std::pair<std::string, std::vector<std::string>>>
173 &connectionNames = object.second;
174 if (connectionNames.size() < 1)
175 {
176 continue;
177 }
Ed Tanous029573d2019-02-01 10:57:49 -0800178
James Feist5bc2dc82019-10-22 14:33:16 -0700179 auto memoryHealth = std::make_shared<HealthPopulate>(
180 aResp, aResp->res.jsonValue["MemorySummary"]["Status"]);
181
182 auto cpuHealth = std::make_shared<HealthPopulate>(
183 aResp, aResp->res.jsonValue["ProcessorSummary"]["Status"]);
184
185 systemHealth->children.emplace_back(memoryHealth);
186 systemHealth->children.emplace_back(cpuHealth);
187
Ed Tanous029573d2019-02-01 10:57:49 -0800188 // This is not system, so check if it's cpu, dimm, UUID or
189 // BiosVer
190 for (const auto &connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700191 {
Ed Tanous029573d2019-02-01 10:57:49 -0800192 for (const auto &interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700193 {
Ed Tanous029573d2019-02-01 10:57:49 -0800194 if (interfaceName ==
195 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700196 {
Ed Tanous029573d2019-02-01 10:57:49 -0800197 BMCWEB_LOG_DEBUG
198 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500199
Ed Tanous029573d2019-02-01 10:57:49 -0800200 crow::connections::systemBus->async_method_call(
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500201 [aResp, service{connection.first},
202 path(std::move(path))](
203 const boost::system::error_code ec,
204 const std::vector<
205 std::pair<std::string, VariantType>>
206 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800207 if (ec)
208 {
209 BMCWEB_LOG_ERROR
210 << "DBUS response error " << ec;
211 messages::internalError(aResp->res);
212 return;
213 }
214 BMCWEB_LOG_DEBUG << "Got "
215 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500216 << " Dimm properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500217
218 if (properties.size() > 0)
Ed Tanous029573d2019-02-01 10:57:49 -0800219 {
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500220 for (const std::pair<std::string,
221 VariantType>
222 &property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700223 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800224 if (property.first !=
225 "MemorySizeInKB")
Ed Tanous6c34de42018-08-29 13:37:36 -0700226 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800227 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700228 }
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800229 const uint32_t *value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500230 std::get_if<uint32_t>(
231 &property.second);
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800232 if (value == nullptr)
233 {
234 BMCWEB_LOG_DEBUG
235 << "Find incorrect type of "
236 "MemorySize";
237 continue;
238 }
239 nlohmann::json &totalMemory =
240 aResp->res
241 .jsonValue["MemorySummar"
242 "y"]
243 ["TotalSystemMe"
244 "moryGiB"];
245 uint64_t *preValue =
246 totalMemory
247 .get_ptr<uint64_t *>();
248 if (preValue == nullptr)
249 {
250 continue;
251 }
252 aResp->res
253 .jsonValue["MemorySummary"]
254 ["TotalSystemMemoryGi"
255 "B"] =
256 *value / (1024 * 1024) +
257 *preValue;
258 aResp->res
259 .jsonValue["MemorySummary"]
260 ["Status"]["State"] =
261 "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700262 }
Ed Tanous029573d2019-02-01 10:57:49 -0800263 }
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500264 else
265 {
266 auto getDimmProperties =
267 [aResp](
268 const boost::system::error_code
269 ec,
270 const std::variant<bool>
271 &dimmState) {
272 if (ec)
273 {
274 BMCWEB_LOG_ERROR
275 << "DBUS response "
276 "error "
277 << ec;
278 return;
279 }
280 updateDimmProperties(aResp,
281 dimmState);
282 };
283 crow::connections::systemBus
284 ->async_method_call(
285 std::move(getDimmProperties),
286 service, path,
287 "org.freedesktop.DBus."
288 "Properties",
289 "Get",
290 "xyz.openbmc_project.State."
291 "Decorator.OperationalStatus",
292 "Functional");
293 }
Ed Tanous029573d2019-02-01 10:57:49 -0800294 },
295 connection.first, path,
296 "org.freedesktop.DBus.Properties", "GetAll",
297 "xyz.openbmc_project.Inventory.Item.Dimm");
James Feist5bc2dc82019-10-22 14:33:16 -0700298
299 memoryHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800300 }
301 else if (interfaceName ==
302 "xyz.openbmc_project.Inventory.Item.Cpu")
303 {
304 BMCWEB_LOG_DEBUG
305 << "Found Cpu, now get its properties.";
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500306
Ed Tanous029573d2019-02-01 10:57:49 -0800307 crow::connections::systemBus->async_method_call(
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500308 [aResp, service{connection.first},
309 path(std::move(path))](
310 const boost::system::error_code ec,
311 const std::vector<
312 std::pair<std::string, VariantType>>
313 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800314 if (ec)
315 {
316 BMCWEB_LOG_ERROR
317 << "DBUS response error " << ec;
318 messages::internalError(aResp->res);
319 return;
320 }
321 BMCWEB_LOG_DEBUG << "Got "
322 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500323 << " Cpu properties.";
Ed Tanous04a258f2018-10-15 08:00:41 -0700324
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500325 if (properties.size() > 0)
326 {
327 for (const auto &property : properties)
328 {
329 if (property.first ==
330 "ProcessorFamily")
331 {
332 const std::string *value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500333 std::get_if<std::string>(
334 &property.second);
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500335 if (value != nullptr)
336 {
337 nlohmann::json
338 &procSummary =
339 aResp->res.jsonValue
340 ["ProcessorSumm"
341 "ary"];
342 nlohmann::json &procCount =
343 procSummary["Count"];
James Feistb4b95952019-12-05 15:01:55 -0800344
345 auto procCountPtr =
346 procCount.get_ptr<
347 nlohmann::json::
348 number_integer_t
349 *>();
350 if (procCountPtr != nullptr)
351 {
352 // shouldn't be possible
353 // to be nullptr
354 *procCountPtr += 1;
355 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500356 procSummary["Status"]
357 ["State"] =
358 "Enabled";
359 procSummary["Model"] =
360 *value;
361 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700362 }
363 }
Ed Tanous029573d2019-02-01 10:57:49 -0800364 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500365 else
366 {
367 auto getCpuPresenceState =
368 [aResp](
369 const boost::system::error_code
370 ec,
371 const std::variant<bool>
372 &cpuPresenceCheck) {
373 if (ec)
374 {
375 BMCWEB_LOG_ERROR
376 << "DBUS response "
377 "error "
378 << ec;
379 return;
380 }
381 modifyCpuPresenceState(
382 aResp, cpuPresenceCheck);
383 };
384
385 auto getCpuFunctionalState =
386 [aResp](
387 const boost::system::error_code
388 ec,
389 const std::variant<bool>
390 &cpuFunctionalCheck) {
391 if (ec)
392 {
393 BMCWEB_LOG_ERROR
394 << "DBUS response "
395 "error "
396 << ec;
397 return;
398 }
399 modifyCpuFunctionalState(
400 aResp, cpuFunctionalCheck);
401 };
402 // Get the Presence of CPU
403 crow::connections::systemBus
404 ->async_method_call(
405 std::move(getCpuPresenceState),
406 service, path,
407 "org.freedesktop.DBus."
408 "Properties",
409 "Get",
410 "xyz.openbmc_project.Inventory."
411 "Item",
412 "Present");
413
414 // Get the Functional State
415 crow::connections::systemBus
416 ->async_method_call(
417 std::move(
418 getCpuFunctionalState),
419 service, path,
420 "org.freedesktop.DBus."
421 "Properties",
422 "Get",
423 "xyz.openbmc_project.State."
424 "Decorator."
425 "OperationalStatus",
426 "Functional");
427
428 // Get the MODEL from
429 // xyz.openbmc_project.Inventory.Decorator.Asset
430 // support it later as Model is Empty
431 // currently.
432 }
Ed Tanous029573d2019-02-01 10:57:49 -0800433 },
434 connection.first, path,
435 "org.freedesktop.DBus.Properties", "GetAll",
436 "xyz.openbmc_project.Inventory.Item.Cpu");
James Feist5bc2dc82019-10-22 14:33:16 -0700437
438 cpuHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800439 }
440 else if (interfaceName ==
441 "xyz.openbmc_project.Common.UUID")
442 {
443 BMCWEB_LOG_DEBUG
444 << "Found UUID, now get its properties.";
445 crow::connections::systemBus->async_method_call(
446 [aResp](const boost::system::error_code ec,
Ed Tanous6c34de42018-08-29 13:37:36 -0700447 const std::vector<
448 std::pair<std::string, VariantType>>
449 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800450 if (ec)
451 {
452 BMCWEB_LOG_DEBUG
453 << "DBUS response error " << ec;
454 messages::internalError(aResp->res);
455 return;
456 }
457 BMCWEB_LOG_DEBUG << "Got "
458 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500459 << " UUID properties.";
Ed Tanous029573d2019-02-01 10:57:49 -0800460 for (const std::pair<std::string,
461 VariantType>
462 &property : properties)
463 {
Ed Tanous029573d2019-02-01 10:57:49 -0800464 if (property.first == "UUID")
465 {
466 const std::string *value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500467 std::get_if<std::string>(
468 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700469
Ed Tanous029573d2019-02-01 10:57:49 -0800470 if (value != nullptr)
471 {
472 std::string valueStr = *value;
473 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700474 {
Ed Tanous029573d2019-02-01 10:57:49 -0800475 valueStr.insert(8, 1, '-');
476 valueStr.insert(13, 1, '-');
477 valueStr.insert(18, 1, '-');
478 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700479 }
Ed Tanous029573d2019-02-01 10:57:49 -0800480 BMCWEB_LOG_DEBUG << "UUID = "
481 << valueStr;
482 aResp->res.jsonValue["UUID"] =
483 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700484 }
485 }
Ed Tanous029573d2019-02-01 10:57:49 -0800486 }
487 },
488 connection.first, path,
489 "org.freedesktop.DBus.Properties", "GetAll",
490 "xyz.openbmc_project.Common.UUID");
491 }
492 else if (interfaceName ==
493 "xyz.openbmc_project.Inventory.Item.System")
494 {
495 crow::connections::systemBus->async_method_call(
496 [aResp](const boost::system::error_code ec,
497 const std::vector<
498 std::pair<std::string, VariantType>>
499 &propertiesList) {
500 if (ec)
501 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700502 // doesn't have to include this
503 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800504 return;
505 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500506 BMCWEB_LOG_DEBUG
507 << "Got " << propertiesList.size()
508 << " properties for system";
Ed Tanous029573d2019-02-01 10:57:49 -0800509 for (const std::pair<std::string,
510 VariantType>
511 &property : propertiesList)
512 {
beccabroekfc5afcf2019-03-05 14:35:15 -0600513 const std::string &propertyName =
514 property.first;
515 if ((propertyName == "PartNumber") ||
516 (propertyName == "SerialNumber") ||
517 (propertyName == "Manufacturer") ||
518 (propertyName == "Model"))
Ed Tanous029573d2019-02-01 10:57:49 -0800519 {
beccabroekfc5afcf2019-03-05 14:35:15 -0600520 const std::string *value =
521 std::get_if<std::string>(
522 &property.second);
523 if (value != nullptr)
524 {
525 aResp->res
526 .jsonValue[propertyName] =
527 *value;
528 }
Ed Tanous029573d2019-02-01 10:57:49 -0800529 }
530 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500531
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600532 // Grab the bios version
533 fw_util::getActiveFwVersion(
534 aResp, fw_util::biosPurpose,
535 "BiosVersion");
Ed Tanous029573d2019-02-01 10:57:49 -0800536 },
537 connection.first, path,
538 "org.freedesktop.DBus.Properties", "GetAll",
539 "xyz.openbmc_project.Inventory.Decorator."
540 "Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700541
542 crow::connections::systemBus->async_method_call(
543 [aResp](
544 const boost::system::error_code ec,
545 const std::variant<std::string> &property) {
546 if (ec)
547 {
548 // doesn't have to include this
549 // interface
550 return;
551 }
552
553 const std::string *value =
554 std::get_if<std::string>(&property);
555 if (value != nullptr)
556 {
557 aResp->res.jsonValue["AssetTag"] =
558 *value;
559 }
560 },
561 connection.first, path,
562 "org.freedesktop.DBus.Properties", "Get",
563 "xyz.openbmc_project.Inventory.Decorator."
564 "AssetTag",
565 "AssetTag");
Ed Tanous6c34de42018-08-29 13:37:36 -0700566 }
567 }
568 }
569 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700570 },
571 "xyz.openbmc_project.ObjectMapper",
572 "/xyz/openbmc_project/object_mapper",
573 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700574 "/xyz/openbmc_project/inventory", int32_t(0),
575 std::array<const char *, 5>{
576 "xyz.openbmc_project.Inventory.Decorator.Asset",
577 "xyz.openbmc_project.Inventory.Item.Cpu",
578 "xyz.openbmc_project.Inventory.Item.Dimm",
579 "xyz.openbmc_project.Inventory.Item.System",
580 "xyz.openbmc_project.Common.UUID",
581 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700582}
583
584/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700585 * @brief Retrieves host state properties over dbus
586 *
587 * @param[in] aResp Shared pointer for completing asynchronous calls.
588 *
589 * @return None.
590 */
591void getHostState(std::shared_ptr<AsyncResp> aResp)
592{
593 BMCWEB_LOG_DEBUG << "Get host information.";
594 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800595 [aResp](const boost::system::error_code ec,
596 const std::variant<std::string> &hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700597 if (ec)
598 {
599 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700600 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700601 return;
602 }
Ed Tanous66173382018-08-15 18:20:59 -0700603
Ed Tanousabf2add2019-01-22 16:40:12 -0800604 const std::string *s = std::get_if<std::string>(&hostState);
Ed Tanous66173382018-08-15 18:20:59 -0700605 BMCWEB_LOG_DEBUG << "Host state: " << *s;
606 if (s != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700607 {
Ed Tanous66173382018-08-15 18:20:59 -0700608 // Verify Host State
Andrew Geissler94732662019-01-08 19:32:16 -0800609 if (*s == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700610 {
Ed Tanous66173382018-08-15 18:20:59 -0700611 aResp->res.jsonValue["PowerState"] = "On";
612 aResp->res.jsonValue["Status"]["State"] = "Enabled";
613 }
Andrew Geissler83935af2020-02-13 10:24:53 -0600614 else if (*s == "xyz.openbmc_project.State.Host.HostState."
Gunnar Mills8c888602020-05-01 14:25:09 -0500615 "Quiesced")
616 {
617 aResp->res.jsonValue["PowerState"] = "On";
618 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
619 }
620 else if (*s == "xyz.openbmc_project.State.Host.HostState."
Andrew Geissler83935af2020-02-13 10:24:53 -0600621 "DiagnosticMode")
622 {
623 aResp->res.jsonValue["PowerState"] = "On";
624 aResp->res.jsonValue["Status"]["State"] = "InTest";
625 }
Ed Tanous66173382018-08-15 18:20:59 -0700626 else
627 {
628 aResp->res.jsonValue["PowerState"] = "Off";
629 aResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700630 }
631 }
632 },
633 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Ed Tanous66173382018-08-15 18:20:59 -0700634 "org.freedesktop.DBus.Properties", "Get",
635 "xyz.openbmc_project.State.Host", "CurrentHostState");
Ed Tanous6c34de42018-08-29 13:37:36 -0700636}
637
638/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530639 * @brief Traslates boot source DBUS property value to redfish.
640 *
641 * @param[in] dbusSource The boot source in DBUS speak.
642 *
643 * @return Returns as a string, the boot source in Redfish terms. If translation
644 * cannot be done, returns an empty string.
645 */
646static std::string dbusToRfBootSource(const std::string &dbusSource)
647{
648 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
649 {
650 return "None";
651 }
652 else if (dbusSource ==
653 "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
654 {
655 return "Hdd";
656 }
657 else if (dbusSource ==
Santosh Puranika71dc0b2019-05-23 20:10:49 +0530658 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530659 {
660 return "Cd";
661 }
662 else if (dbusSource ==
663 "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
664 {
665 return "Pxe";
666 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700667 else if (dbusSource ==
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700668 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700669 {
670 return "Usb";
671 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530672 else
673 {
674 return "";
675 }
676}
677
678/**
679 * @brief Traslates boot mode DBUS property value to redfish.
680 *
681 * @param[in] dbusMode The boot mode in DBUS speak.
682 *
683 * @return Returns as a string, the boot mode in Redfish terms. If translation
684 * cannot be done, returns an empty string.
685 */
686static std::string dbusToRfBootMode(const std::string &dbusMode)
687{
688 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
689 {
690 return "None";
691 }
692 else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
693 {
694 return "Diags";
695 }
696 else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
697 {
698 return "BiosSetup";
699 }
700 else
701 {
702 return "";
703 }
704}
705
706/**
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700707 * @brief Traslates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530708 *
709 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700710 * @param[out] bootSource The DBus source
711 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530712 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700713 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530714 */
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700715static int assignBootParameters(std::shared_ptr<AsyncResp> aResp,
716 const std::string &rfSource,
717 std::string &bootSource, std::string &bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530718{
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700719 // The caller has initialized the bootSource and bootMode to:
720 // bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
721 // bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
722 // Only modify the bootSource/bootMode variable needed to achieve the
723 // desired boot action.
724
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530725 if (rfSource == "None")
726 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700727 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530728 }
729 else if (rfSource == "Pxe")
730 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700731 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
732 }
733 else if (rfSource == "Hdd")
734 {
735 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
736 }
737 else if (rfSource == "Diags")
738 {
739 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
740 }
741 else if (rfSource == "Cd")
742 {
743 bootSource =
744 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
745 }
746 else if (rfSource == "BiosSetup")
747 {
748 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530749 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700750 else if (rfSource == "Usb")
751 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700752 bootSource =
753 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700754 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530755 else
756 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700757 BMCWEB_LOG_DEBUG << "Invalid property value for "
758 "BootSourceOverrideTarget: "
759 << bootSource;
760 messages::propertyValueNotInList(aResp->res, rfSource,
761 "BootSourceTargetOverride");
762 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530763 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700764 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530765}
766
767/**
768 * @brief Retrieves boot mode over DBUS and fills out the response
769 *
770 * @param[in] aResp Shared pointer for generating response message.
771 * @param[in] bootDbusObj The dbus object to query for boot properties.
772 *
773 * @return None.
774 */
775static void getBootMode(std::shared_ptr<AsyncResp> aResp,
776 std::string bootDbusObj)
777{
778 crow::connections::systemBus->async_method_call(
779 [aResp](const boost::system::error_code ec,
780 const std::variant<std::string> &bootMode) {
781 if (ec)
782 {
783 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
784 messages::internalError(aResp->res);
785 return;
786 }
787
788 const std::string *bootModeStr =
789 std::get_if<std::string>(&bootMode);
790
791 if (!bootModeStr)
792 {
793 messages::internalError(aResp->res);
794 return;
795 }
796
797 BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
798
799 // TODO (Santosh): Do we need to support override mode?
800 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = "Legacy";
801 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
802 "AllowableValues"] = {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700803 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530804
805 if (*bootModeStr !=
806 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
807 {
808 auto rfMode = dbusToRfBootMode(*bootModeStr);
809 if (!rfMode.empty())
810 {
811 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
812 rfMode;
813 }
814 }
815
816 // If the BootSourceOverrideTarget is still "None" at the end,
817 // reset the BootSourceOverrideEnabled to indicate that
818 // overrides are disabled
819 if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] ==
820 "None")
821 {
822 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
823 "Disabled";
824 }
825 },
826 "xyz.openbmc_project.Settings", bootDbusObj,
827 "org.freedesktop.DBus.Properties", "Get",
828 "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
829}
830
831/**
832 * @brief Retrieves boot source over DBUS
833 *
834 * @param[in] aResp Shared pointer for generating response message.
835 * @param[in] oneTimeEnable Boolean to indicate boot properties are one-time.
836 *
837 * @return None.
838 */
839static void getBootSource(std::shared_ptr<AsyncResp> aResp, bool oneTimeEnabled)
840{
841 std::string bootDbusObj =
842 oneTimeEnabled ? "/xyz/openbmc_project/control/host0/boot/one_time"
843 : "/xyz/openbmc_project/control/host0/boot";
844
845 BMCWEB_LOG_DEBUG << "Is one time: " << oneTimeEnabled;
846 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
847 (oneTimeEnabled) ? "Once" : "Continuous";
848
849 crow::connections::systemBus->async_method_call(
850 [aResp, bootDbusObj](const boost::system::error_code ec,
851 const std::variant<std::string> &bootSource) {
852 if (ec)
853 {
854 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
855 messages::internalError(aResp->res);
856 return;
857 }
858
859 const std::string *bootSourceStr =
860 std::get_if<std::string>(&bootSource);
861
862 if (!bootSourceStr)
863 {
864 messages::internalError(aResp->res);
865 return;
866 }
867 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
868
869 auto rfSource = dbusToRfBootSource(*bootSourceStr);
870 if (!rfSource.empty())
871 {
872 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
873 rfSource;
874 }
875 },
876 "xyz.openbmc_project.Settings", bootDbusObj,
877 "org.freedesktop.DBus.Properties", "Get",
878 "xyz.openbmc_project.Control.Boot.Source", "BootSource");
879 getBootMode(std::move(aResp), std::move(bootDbusObj));
880}
881
882/**
883 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
884 * get boot source and boot mode.
885 *
886 * @param[in] aResp Shared pointer for generating response message.
887 *
888 * @return None.
889 */
890static void getBootProperties(std::shared_ptr<AsyncResp> aResp)
891{
892 BMCWEB_LOG_DEBUG << "Get boot information.";
893
894 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800895 [aResp](const boost::system::error_code ec,
Patrick Williams19bd78d2020-05-13 17:38:24 -0500896 const std::variant<bool> &oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530897 if (ec)
898 {
899 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
James Feist2a833c72019-07-19 10:17:13 -0700900 // not an error, don't have to have the interface
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530901 return;
902 }
903
904 const bool *oneTimePtr = std::get_if<bool>(&oneTime);
905
906 if (!oneTimePtr)
907 {
908 messages::internalError(aResp->res);
909 return;
910 }
911 getBootSource(aResp, *oneTimePtr);
912 },
913 "xyz.openbmc_project.Settings",
914 "/xyz/openbmc_project/control/host0/boot/one_time",
915 "org.freedesktop.DBus.Properties", "Get",
916 "xyz.openbmc_project.Object.Enable", "Enabled");
917}
918
919/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -0500920 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
921 *
922 * @param[in] aResp Shared pointer for generating response message.
923 *
924 * @return None.
925 */
926void getAutomaticRetry(std::shared_ptr<AsyncResp> aResp)
927{
928 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
929
930 crow::connections::systemBus->async_method_call(
931 [aResp](const boost::system::error_code ec,
932 std::variant<bool> &autoRebootEnabled) {
933 if (ec)
934 {
935 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
936 return;
937 }
938
939 const bool *autoRebootEnabledPtr =
940 std::get_if<bool>(&autoRebootEnabled);
941
942 if (!autoRebootEnabledPtr)
943 {
944 messages::internalError(aResp->res);
945 return;
946 }
947
948 BMCWEB_LOG_DEBUG << "Auto Reboot: " << *autoRebootEnabledPtr;
949 if (*autoRebootEnabledPtr == true)
950 {
951 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
952 "RetryAttempts";
953 // If AutomaticRetry (AutoReboot) is enabled see how many
954 // attempts are left
955 crow::connections::systemBus->async_method_call(
956 [aResp](const boost::system::error_code ec,
957 std::variant<uint32_t> &autoRebootAttemptsLeft) {
958 if (ec)
959 {
960 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
961 return;
962 }
963
964 const uint32_t *autoRebootAttemptsLeftPtr =
965 std::get_if<uint32_t>(&autoRebootAttemptsLeft);
966
967 if (!autoRebootAttemptsLeftPtr)
968 {
969 messages::internalError(aResp->res);
970 return;
971 }
972
973 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
974 << *autoRebootAttemptsLeftPtr;
975
976 aResp->res
977 .jsonValue["Boot"]
978 ["RemainingAutomaticRetryAttempts"] =
979 *autoRebootAttemptsLeftPtr;
980 },
981 "xyz.openbmc_project.State.Host",
982 "/xyz/openbmc_project/state/host0",
983 "org.freedesktop.DBus.Properties", "Get",
984 "xyz.openbmc_project.Control.Boot.RebootAttempts",
985 "AttemptsLeft");
986 }
987 else
988 {
989 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
990 "Disabled";
991 }
992
993 // Not on D-Bus. Hardcoded here:
994 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
995 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -0500996
997 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
998 // and RetryAttempts. OpenBMC only supports Disabled and
999 // RetryAttempts.
1000 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig@Redfish."
1001 "AllowableValues"] = {"Disabled",
1002 "RetryAttempts"};
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001003 },
1004 "xyz.openbmc_project.Settings",
1005 "/xyz/openbmc_project/control/host0/auto_reboot",
1006 "org.freedesktop.DBus.Properties", "Get",
1007 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot");
1008}
1009
1010/**
George Liuc6a620f2020-04-10 17:18:11 +08001011 * @brief Retrieves power restore policy over DBUS.
1012 *
1013 * @param[in] aResp Shared pointer for generating response message.
1014 *
1015 * @return None.
1016 */
1017void getPowerRestorePolicy(std::shared_ptr<AsyncResp> aResp)
1018{
1019 BMCWEB_LOG_DEBUG << "Get power restore policy";
1020
1021 crow::connections::systemBus->async_method_call(
1022 [aResp](const boost::system::error_code ec,
Patrick Williams19bd78d2020-05-13 17:38:24 -05001023 std::variant<std::string> &policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001024 if (ec)
1025 {
1026 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1027 return;
1028 }
1029
1030 const boost::container::flat_map<std::string, std::string>
1031 policyMaps = {
1032 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1033 "AlwaysOn",
1034 "AlwaysOn"},
1035 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1036 "AlwaysOff",
1037 "AlwaysOff"},
1038 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1039 "LastState",
1040 "LastState"}};
1041
1042 const std::string *policyPtr = std::get_if<std::string>(&policy);
1043
1044 if (!policyPtr)
1045 {
1046 messages::internalError(aResp->res);
1047 return;
1048 }
1049
1050 auto policyMapsIt = policyMaps.find(*policyPtr);
1051 if (policyMapsIt == policyMaps.end())
1052 {
1053 messages::internalError(aResp->res);
1054 return;
1055 }
1056
1057 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
1058 },
1059 "xyz.openbmc_project.Settings",
1060 "/xyz/openbmc_project/control/host0/power_restore_policy",
1061 "org.freedesktop.DBus.Properties", "Get",
1062 "xyz.openbmc_project.Control.Power.RestorePolicy",
1063 "PowerRestorePolicy");
1064}
1065
1066/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301067 * @brief Sets boot properties into DBUS object(s).
1068 *
1069 * @param[in] aResp Shared pointer for generating response message.
1070 * @param[in] oneTimeEnabled Is "one-time" setting already enabled.
1071 * @param[in] bootSource The boot source to set.
1072 * @param[in] bootEnable The source override "enable" to set.
1073 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001074 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301075 */
1076static void setBootModeOrSource(std::shared_ptr<AsyncResp> aResp,
1077 bool oneTimeEnabled,
1078 std::optional<std::string> bootSource,
1079 std::optional<std::string> bootEnable)
1080{
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001081 std::string bootSourceStr =
1082 "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
1083 std::string bootModeStr =
1084 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301085 bool oneTimeSetting = oneTimeEnabled;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001086 bool useBootSource = true;
1087
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301088 // Validate incoming parameters
1089 if (bootEnable)
1090 {
1091 if (*bootEnable == "Once")
1092 {
1093 oneTimeSetting = true;
1094 }
1095 else if (*bootEnable == "Continuous")
1096 {
1097 oneTimeSetting = false;
1098 }
1099 else if (*bootEnable == "Disabled")
1100 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001101 BMCWEB_LOG_DEBUG << "Boot source override will be disabled";
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301102 oneTimeSetting = false;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001103 useBootSource = false;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301104 }
1105 else
1106 {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301107 BMCWEB_LOG_DEBUG << "Unsupported value for "
1108 "BootSourceOverrideEnabled: "
1109 << *bootEnable;
1110 messages::propertyValueNotInList(aResp->res, *bootEnable,
1111 "BootSourceOverrideEnabled");
1112 return;
1113 }
1114 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301115
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001116 if (bootSource && useBootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301117 {
1118 // Source target specified
1119 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1120 // Figure out which DBUS interface and property to use
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001121 if (assignBootParameters(aResp, *bootSource, bootSourceStr,
1122 bootModeStr))
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301123 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001124 BMCWEB_LOG_DEBUG
1125 << "Invalid property value for BootSourceOverrideTarget: "
1126 << *bootSource;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301127 messages::propertyValueNotInList(aResp->res, *bootSource,
1128 "BootSourceTargetOverride");
1129 return;
1130 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001131 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301132
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001133 // Act on validated parameters
1134 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1135 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
1136 const char *bootObj =
1137 oneTimeSetting ? "/xyz/openbmc_project/control/host0/boot/one_time"
1138 : "/xyz/openbmc_project/control/host0/boot";
1139
1140 crow::connections::systemBus->async_method_call(
1141 [aResp](const boost::system::error_code ec) {
1142 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301143 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001144 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1145 messages::internalError(aResp->res);
1146 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301147 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001148 BMCWEB_LOG_DEBUG << "Boot source update done.";
1149 },
1150 "xyz.openbmc_project.Settings", bootObj,
1151 "org.freedesktop.DBus.Properties", "Set",
1152 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1153 std::variant<std::string>(bootSourceStr));
1154
1155 crow::connections::systemBus->async_method_call(
1156 [aResp](const boost::system::error_code ec) {
1157 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301158 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001159 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1160 messages::internalError(aResp->res);
1161 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301162 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001163 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1164 },
1165 "xyz.openbmc_project.Settings", bootObj,
1166 "org.freedesktop.DBus.Properties", "Set",
1167 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1168 std::variant<std::string>(bootModeStr));
1169
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301170 crow::connections::systemBus->async_method_call(
1171 [aResp{std::move(aResp)}](const boost::system::error_code ec) {
1172 if (ec)
1173 {
1174 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1175 messages::internalError(aResp->res);
1176 return;
1177 }
1178 BMCWEB_LOG_DEBUG << "Boot enable update done.";
1179 },
1180 "xyz.openbmc_project.Settings",
1181 "/xyz/openbmc_project/control/host0/boot/one_time",
1182 "org.freedesktop.DBus.Properties", "Set",
1183 "xyz.openbmc_project.Object.Enable", "Enabled",
1184 std::variant<bool>(oneTimeSetting));
1185}
1186
1187/**
1188 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
1189 * set boot source/boot mode properties.
1190 *
1191 * @param[in] aResp Shared pointer for generating response message.
1192 * @param[in] bootSource The boot source from incoming RF request.
1193 * @param[in] bootEnable The boot override enable from incoming RF request.
1194 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001195 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301196 */
Gunnar Mills69f35302020-05-17 16:06:31 -05001197static void setBootSourceProperties(std::shared_ptr<AsyncResp> aResp,
1198 std::optional<std::string> bootSource,
1199 std::optional<std::string> bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301200{
1201 BMCWEB_LOG_DEBUG << "Set boot information.";
1202
1203 crow::connections::systemBus->async_method_call(
Johnathan Mantey265c1602019-08-08 11:02:51 -07001204 [aResp, bootSource{std::move(bootSource)},
Patrick Williams19bd78d2020-05-13 17:38:24 -05001205 bootEnable{std::move(bootEnable)}](const boost::system::error_code ec,
1206 const std::variant<bool> &oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301207 if (ec)
1208 {
1209 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1210 messages::internalError(aResp->res);
1211 return;
1212 }
1213
1214 const bool *oneTimePtr = std::get_if<bool>(&oneTime);
1215
1216 if (!oneTimePtr)
1217 {
1218 messages::internalError(aResp->res);
1219 return;
1220 }
1221
1222 BMCWEB_LOG_DEBUG << "Got one time: " << *oneTimePtr;
1223
1224 setBootModeOrSource(aResp, *oneTimePtr, std::move(bootSource),
1225 std::move(bootEnable));
1226 },
1227 "xyz.openbmc_project.Settings",
1228 "/xyz/openbmc_project/control/host0/boot/one_time",
1229 "org.freedesktop.DBus.Properties", "Get",
1230 "xyz.openbmc_project.Object.Enable", "Enabled");
1231}
1232
George Liuc6a620f2020-04-10 17:18:11 +08001233/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001234 * @brief Sets automaticRetry (Auto Reboot)
1235 *
1236 * @param[in] aResp Shared pointer for generating response message.
1237 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1238 *
1239 * @return None.
1240 */
1241static void setAutomaticRetry(std::shared_ptr<AsyncResp> aResp,
1242 const std::string &&automaticRetryConfig)
1243{
1244 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1245
1246 // OpenBMC only supports "Disabled" and "RetryAttempts".
1247 bool autoRebootEnabled;
1248
1249 if (automaticRetryConfig == "Disabled")
1250 {
1251 autoRebootEnabled = false;
1252 }
1253 else if (automaticRetryConfig == "RetryAttempts")
1254 {
1255 autoRebootEnabled = true;
1256 }
1257 else
1258 {
1259 BMCWEB_LOG_DEBUG << "Invalid property value for "
1260 "AutomaticRetryConfig: "
1261 << automaticRetryConfig;
1262 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1263 "AutomaticRetryConfig");
1264 return;
1265 }
1266
1267 crow::connections::systemBus->async_method_call(
1268 [aResp](const boost::system::error_code ec) {
1269 if (ec)
1270 {
1271 messages::internalError(aResp->res);
1272 return;
1273 }
1274 },
1275 "xyz.openbmc_project.Settings",
1276 "/xyz/openbmc_project/control/host0/auto_reboot",
1277 "org.freedesktop.DBus.Properties", "Set",
1278 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1279 std::variant<bool>(autoRebootEnabled));
1280}
1281
1282/**
George Liuc6a620f2020-04-10 17:18:11 +08001283 * @brief Sets power restore policy properties.
1284 *
1285 * @param[in] aResp Shared pointer for generating response message.
1286 * @param[in] policy power restore policy properties from request.
1287 *
1288 * @return None.
1289 */
1290static void setPowerRestorePolicy(std::shared_ptr<AsyncResp> aResp,
1291 std::optional<std::string> policy)
1292{
1293 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1294
1295 const boost::container::flat_map<std::string, std::string> policyMaps = {
1296 {"AlwaysOn", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1297 "AlwaysOn"},
1298 {"AlwaysOff", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1299 "AlwaysOff"},
1300 {"LastState", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1301 "LastState"}};
1302
1303 std::string powerRestorPolicy;
1304
1305 auto policyMapsIt = policyMaps.find(*policy);
1306 if (policyMapsIt == policyMaps.end())
1307 {
1308 messages::internalError(aResp->res);
1309 return;
1310 }
1311
1312 powerRestorPolicy = policyMapsIt->second;
1313
1314 crow::connections::systemBus->async_method_call(
1315 [aResp](const boost::system::error_code ec) {
1316 if (ec)
1317 {
1318 messages::internalError(aResp->res);
1319 return;
1320 }
1321 },
1322 "xyz.openbmc_project.Settings",
1323 "/xyz/openbmc_project/control/host0/power_restore_policy",
1324 "org.freedesktop.DBus.Properties", "Set",
1325 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1326 std::variant<std::string>(powerRestorPolicy));
1327}
1328
AppaRao Pulia6349912019-10-18 17:16:08 +05301329#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1330/**
1331 * @brief Retrieves provisioning status
1332 *
1333 * @param[in] aResp Shared pointer for completing asynchronous calls.
1334 *
1335 * @return None.
1336 */
1337void getProvisioningStatus(std::shared_ptr<AsyncResp> aResp)
1338{
1339 BMCWEB_LOG_DEBUG << "Get OEM information.";
1340 crow::connections::systemBus->async_method_call(
1341 [aResp](const boost::system::error_code ec,
1342 const std::vector<std::pair<std::string, VariantType>>
1343 &propertiesList) {
1344 if (ec)
1345 {
1346 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1347 messages::internalError(aResp->res);
1348 return;
1349 }
1350
1351 const bool *provState = nullptr;
1352 const bool *lockState = nullptr;
1353 for (const std::pair<std::string, VariantType> &property :
1354 propertiesList)
1355 {
1356 if (property.first == "UfmProvisioned")
1357 {
1358 provState = std::get_if<bool>(&property.second);
1359 }
1360 else if (property.first == "UfmLocked")
1361 {
1362 lockState = std::get_if<bool>(&property.second);
1363 }
1364 }
1365
1366 if ((provState == nullptr) || (lockState == nullptr))
1367 {
1368 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1369 messages::internalError(aResp->res);
1370 return;
1371 }
1372
1373 nlohmann::json &oemPFR =
1374 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1375 if (*provState == true)
1376 {
1377 if (*lockState == true)
1378 {
1379 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1380 }
1381 else
1382 {
1383 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
1384 }
1385 }
1386 else
1387 {
1388 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1389 }
1390 },
1391 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1392 "org.freedesktop.DBus.Properties", "GetAll",
1393 "xyz.openbmc_project.PFR.Attributes");
1394}
1395#endif
1396
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301397/**
Yong Li51709ff2019-09-30 14:13:04 +08001398 * @brief Translates watchdog timeout action DBUS property value to redfish.
1399 *
1400 * @param[in] dbusAction The watchdog timeout action in D-BUS.
1401 *
1402 * @return Returns as a string, the timeout action in Redfish terms. If
1403 * translation cannot be done, returns an empty string.
1404 */
1405static std::string dbusToRfWatchdogAction(const std::string &dbusAction)
1406{
1407 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
1408 {
1409 return "None";
1410 }
1411 else if (dbusAction ==
1412 "xyz.openbmc_project.State.Watchdog.Action.HardReset")
1413 {
1414 return "ResetSystem";
1415 }
1416 else if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
1417 {
1418 return "PowerDown";
1419 }
1420 else if (dbusAction ==
1421 "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
1422 {
1423 return "PowerCycle";
1424 }
1425
1426 return "";
1427}
1428
1429/**
Yong Lic45f0082019-10-10 14:19:01 +08001430 *@brief Translates timeout action from Redfish to DBUS property value.
1431 *
1432 *@param[in] rfAction The timeout action in Redfish.
1433 *
1434 *@return Returns as a string, the time_out action as expected by DBUS.
1435 *If translation cannot be done, returns an empty string.
1436 */
1437
1438static std::string rfToDbusWDTTimeOutAct(const std::string &rfAction)
1439{
1440 if (rfAction == "None")
1441 {
1442 return "xyz.openbmc_project.State.Watchdog.Action.None";
1443 }
1444 else if (rfAction == "PowerCycle")
1445 {
1446 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
1447 }
1448 else if (rfAction == "PowerDown")
1449 {
1450 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
1451 }
1452 else if (rfAction == "ResetSystem")
1453 {
1454 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
1455 }
1456
1457 return "";
1458}
1459
1460/**
Yong Li51709ff2019-09-30 14:13:04 +08001461 * @brief Retrieves host watchdog timer properties over DBUS
1462 *
1463 * @param[in] aResp Shared pointer for completing asynchronous calls.
1464 *
1465 * @return None.
1466 */
1467void getHostWatchdogTimer(std::shared_ptr<AsyncResp> aResp)
1468{
1469 BMCWEB_LOG_DEBUG << "Get host watchodg";
1470 crow::connections::systemBus->async_method_call(
1471 [aResp](const boost::system::error_code ec,
1472 PropertiesType &properties) {
1473 if (ec)
1474 {
1475 // watchdog service is stopped
1476 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1477 return;
1478 }
1479
1480 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
1481
1482 nlohmann::json &hostWatchdogTimer =
1483 aResp->res.jsonValue["HostWatchdogTimer"];
1484
1485 // watchdog service is running/enabled
1486 hostWatchdogTimer["Status"]["State"] = "Enabled";
1487
1488 for (const auto &property : properties)
1489 {
1490 BMCWEB_LOG_DEBUG << "prop=" << property.first;
1491 if (property.first == "Enabled")
1492 {
1493 const bool *state = std::get_if<bool>(&property.second);
1494
1495 if (!state)
1496 {
1497 messages::internalError(aResp->res);
1498 continue;
1499 }
1500
1501 hostWatchdogTimer["FunctionEnabled"] = *state;
1502 }
1503 else if (property.first == "ExpireAction")
1504 {
1505 const std::string *s =
1506 std::get_if<std::string>(&property.second);
1507 if (!s)
1508 {
1509 messages::internalError(aResp->res);
1510 continue;
1511 }
1512
1513 std::string action = dbusToRfWatchdogAction(*s);
1514 if (action.empty())
1515 {
1516 messages::internalError(aResp->res);
1517 continue;
1518 }
1519 hostWatchdogTimer["TimeoutAction"] = action;
1520 }
1521 }
1522 },
1523 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
1524 "org.freedesktop.DBus.Properties", "GetAll",
1525 "xyz.openbmc_project.State.Watchdog");
1526}
1527
1528/**
Yong Lic45f0082019-10-10 14:19:01 +08001529 * @brief Sets Host WatchDog Timer properties.
1530 *
1531 * @param[in] aResp Shared pointer for generating response message.
1532 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
1533 * RF request.
1534 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
1535 *
1536 * @return None.
1537 */
1538static void setWDTProperties(std::shared_ptr<AsyncResp> aResp,
1539 const std::optional<bool> wdtEnable,
1540 const std::optional<std::string> &wdtTimeOutAction)
1541{
1542 BMCWEB_LOG_DEBUG << "Set host watchdog";
1543
1544 if (wdtTimeOutAction)
1545 {
1546 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
1547 // check if TimeOut Action is Valid
1548 if (wdtTimeOutActStr.empty())
1549 {
1550 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
1551 << *wdtTimeOutAction;
1552 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
1553 "TimeoutAction");
1554 return;
1555 }
1556
1557 crow::connections::systemBus->async_method_call(
1558 [aResp](const boost::system::error_code ec) {
1559 if (ec)
1560 {
1561 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1562 messages::internalError(aResp->res);
1563 return;
1564 }
1565 },
1566 "xyz.openbmc_project.Watchdog",
1567 "/xyz/openbmc_project/watchdog/host0",
1568 "org.freedesktop.DBus.Properties", "Set",
1569 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
1570 std::variant<std::string>(wdtTimeOutActStr));
1571 }
1572
1573 if (wdtEnable)
1574 {
1575 crow::connections::systemBus->async_method_call(
1576 [aResp](const boost::system::error_code ec) {
1577 if (ec)
1578 {
1579 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1580 messages::internalError(aResp->res);
1581 return;
1582 }
1583 },
1584 "xyz.openbmc_project.Watchdog",
1585 "/xyz/openbmc_project/watchdog/host0",
1586 "org.freedesktop.DBus.Properties", "Set",
1587 "xyz.openbmc_project.State.Watchdog", "Enabled",
1588 std::variant<bool>(*wdtEnable));
1589 }
1590}
1591
1592/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001593 * SystemsCollection derived class for delivering ComputerSystems Collection
1594 * Schema
1595 */
Ed Tanous1abe55e2018-09-05 08:30:59 -07001596class SystemsCollection : public Node
1597{
1598 public:
1599 SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/")
1600 {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001601 entityPrivileges = {
1602 {boost::beast::http::verb::get, {{"Login"}}},
1603 {boost::beast::http::verb::head, {{"Login"}}},
1604 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1605 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1606 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1607 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1608 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001609
Ed Tanous1abe55e2018-09-05 08:30:59 -07001610 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -07001611 void doGet(crow::Response &res, const crow::Request &req,
1612 const std::vector<std::string> &params) override
1613 {
Sunitha Harish462023a2020-02-19 08:34:59 -06001614 std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous0f74e642018-11-12 15:17:05 -08001615 res.jsonValue["@odata.type"] =
1616 "#ComputerSystemCollection.ComputerSystemCollection";
1617 res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
Ed Tanous0f74e642018-11-12 15:17:05 -08001618 res.jsonValue["Name"] = "Computer System Collection";
Sunitha Harish462023a2020-02-19 08:34:59 -06001619
1620 crow::connections::systemBus->async_method_call(
1621 [asyncResp](const boost::system::error_code ec,
1622 const std::variant<std::string> &hostName) {
1623 nlohmann::json &iface_array =
1624 asyncResp->res.jsonValue["Members"];
1625 iface_array = nlohmann::json::array();
1626 auto &count = asyncResp->res.jsonValue["Members@odata.count"];
1627 count = 0;
1628 if (ec)
1629 {
1630 iface_array.push_back(
1631 {{"@odata.id", "/redfish/v1/Systems/system"}});
1632 count = iface_array.size();
1633 return;
1634 }
1635 BMCWEB_LOG_DEBUG << "Hypervisor is available";
1636 iface_array.push_back(
1637 {{"@odata.id", "/redfish/v1/Systems/system"}});
1638 iface_array.push_back(
1639 {{"@odata.id", "/redfish/v1/Systems/hypervisor"}});
1640 count = iface_array.size();
1641 },
1642 "xyz.openbmc_project.Settings", "/xyz/openbmc_project/network/vmi",
1643 "org.freedesktop.DBus.Properties", "Get",
1644 "xyz.openbmc_project.Network.SystemConfiguration", "HostName");
Ed Tanous1abe55e2018-09-05 08:30:59 -07001645 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001646};
1647
1648/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07001649 * SystemActionsReset class supports handle POST method for Reset action.
1650 * The class retrieves and sends data directly to D-Bus.
1651 */
1652class SystemActionsReset : public Node
1653{
1654 public:
1655 SystemActionsReset(CrowApp &app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001656 Node(app, "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanouscc340dd2018-08-29 13:43:38 -07001657 {
1658 entityPrivileges = {
1659 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1660 }
1661
1662 private:
1663 /**
1664 * Function handles POST method request.
1665 * Analyzes POST body message before sends Reset request data to D-Bus.
1666 */
1667 void doPost(crow::Response &res, const crow::Request &req,
1668 const std::vector<std::string> &params) override
1669 {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001670 auto asyncResp = std::make_shared<AsyncResp>(res);
1671
1672 std::string resetType;
1673 if (!json_util::readJson(req, res, "ResetType", resetType))
Ed Tanouscc340dd2018-08-29 13:43:38 -07001674 {
1675 return;
1676 }
1677
Jason M. Billsd22c8392019-06-03 13:59:03 -07001678 // Get the command and host vs. chassis
Ed Tanous9712f8a2018-09-21 13:38:49 -07001679 std::string command;
Jason M. Billsd22c8392019-06-03 13:59:03 -07001680 bool hostCommand;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001681 if (resetType == "On")
1682 {
1683 command = "xyz.openbmc_project.State.Host.Transition.On";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001684 hostCommand = true;
1685 }
1686 else if (resetType == "ForceOff")
1687 {
1688 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
1689 hostCommand = false;
1690 }
1691 else if (resetType == "ForceOn")
1692 {
1693 command = "xyz.openbmc_project.State.Host.Transition.On";
1694 hostCommand = true;
1695 }
1696 else if (resetType == "ForceRestart")
1697 {
Jason M. Bills86a08512020-02-04 13:15:49 -08001698 command =
1699 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
1700 hostCommand = true;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001701 }
1702 else if (resetType == "GracefulShutdown")
1703 {
1704 command = "xyz.openbmc_project.State.Host.Transition.Off";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001705 hostCommand = true;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001706 }
1707 else if (resetType == "GracefulRestart")
1708 {
Jason M. Bills86a08512020-02-04 13:15:49 -08001709 command =
1710 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001711 hostCommand = true;
1712 }
1713 else if (resetType == "PowerCycle")
1714 {
Jason M. Bills86a08512020-02-04 13:15:49 -08001715 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
1716 hostCommand = true;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001717 }
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001718 else if (resetType == "Nmi")
1719 {
1720 doNMI(asyncResp);
1721 return;
1722 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001723 else
1724 {
Jason M. Billsf12894f2018-10-09 12:45:45 -07001725 messages::actionParameterUnknown(res, "Reset", resetType);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001726 return;
1727 }
1728
Jason M. Billsd22c8392019-06-03 13:59:03 -07001729 if (hostCommand)
1730 {
1731 crow::connections::systemBus->async_method_call(
1732 [asyncResp, resetType](const boost::system::error_code ec) {
1733 if (ec)
1734 {
1735 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1736 if (ec.value() == boost::asio::error::invalid_argument)
1737 {
1738 messages::actionParameterNotSupported(
1739 asyncResp->res, resetType, "Reset");
1740 }
1741 else
1742 {
1743 messages::internalError(asyncResp->res);
1744 }
1745 return;
1746 }
1747 messages::success(asyncResp->res);
1748 },
1749 "xyz.openbmc_project.State.Host",
1750 "/xyz/openbmc_project/state/host0",
1751 "org.freedesktop.DBus.Properties", "Set",
1752 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
1753 std::variant<std::string>{command});
1754 }
1755 else
1756 {
1757 crow::connections::systemBus->async_method_call(
1758 [asyncResp, resetType](const boost::system::error_code ec) {
1759 if (ec)
1760 {
1761 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1762 if (ec.value() == boost::asio::error::invalid_argument)
1763 {
1764 messages::actionParameterNotSupported(
1765 asyncResp->res, resetType, "Reset");
1766 }
1767 else
1768 {
1769 messages::internalError(asyncResp->res);
1770 }
1771 return;
1772 }
1773 messages::success(asyncResp->res);
1774 },
1775 "xyz.openbmc_project.State.Chassis",
1776 "/xyz/openbmc_project/state/chassis0",
1777 "org.freedesktop.DBus.Properties", "Set",
1778 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
1779 std::variant<std::string>{command});
1780 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07001781 }
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001782 /**
1783 * Function transceives data with dbus directly.
1784 */
1785 void doNMI(const std::shared_ptr<AsyncResp> &asyncResp)
1786 {
1787 constexpr char const *serviceName =
1788 "xyz.openbmc_project.Control.Host.NMI";
1789 constexpr char const *objectPath =
1790 "/xyz/openbmc_project/control/host0/nmi";
1791 constexpr char const *interfaceName =
1792 "xyz.openbmc_project.Control.Host.NMI";
1793 constexpr char const *method = "NMI";
1794
1795 crow::connections::systemBus->async_method_call(
1796 [asyncResp](const boost::system::error_code ec) {
1797 if (ec)
1798 {
1799 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
1800 messages::internalError(asyncResp->res);
1801 return;
1802 }
1803 messages::success(asyncResp->res);
1804 },
1805 serviceName, objectPath, interfaceName, method);
1806 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07001807};
1808
1809/**
Ed Tanous66173382018-08-15 18:20:59 -07001810 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001811 */
Ed Tanous1abe55e2018-09-05 08:30:59 -07001812class Systems : public Node
1813{
1814 public:
1815 /*
1816 * Default Constructor
1817 */
Ed Tanous029573d2019-02-01 10:57:49 -08001818 Systems(CrowApp &app) : Node(app, "/redfish/v1/Systems/system/")
Ed Tanous1abe55e2018-09-05 08:30:59 -07001819 {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001820 entityPrivileges = {
1821 {boost::beast::http::verb::get, {{"Login"}}},
1822 {boost::beast::http::verb::head, {{"Login"}}},
1823 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1824 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1825 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1826 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001827 }
1828
Ed Tanous1abe55e2018-09-05 08:30:59 -07001829 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -07001830 /**
1831 * Functions triggers appropriate requests on DBus
1832 */
1833 void doGet(crow::Response &res, const crow::Request &req,
1834 const std::vector<std::string> &params) override
1835 {
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001836 res.jsonValue["@odata.type"] = "#ComputerSystem.v1_11_0.ComputerSystem";
Gunnar Mills450a25c2020-04-14 21:34:07 -05001837 res.jsonValue["Name"] = "system";
Ed Tanous029573d2019-02-01 10:57:49 -08001838 res.jsonValue["Id"] = "system";
Ed Tanous0f74e642018-11-12 15:17:05 -08001839 res.jsonValue["SystemType"] = "Physical";
1840 res.jsonValue["Description"] = "Computer System";
Ed Tanous0f74e642018-11-12 15:17:05 -08001841 res.jsonValue["ProcessorSummary"]["Count"] = 0;
1842 res.jsonValue["ProcessorSummary"]["Status"]["State"] = "Disabled";
Cheng C Yang5fd7ba62019-11-28 15:58:08 +08001843 res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] = uint64_t(0);
Ed Tanous0f74e642018-11-12 15:17:05 -08001844 res.jsonValue["MemorySummary"]["Status"]["State"] = "Disabled";
Ed Tanous029573d2019-02-01 10:57:49 -08001845 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07001846
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001847 res.jsonValue["Processors"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001848 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001849 res.jsonValue["Memory"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001850 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
Nikhil Potadea25aecc2019-08-23 16:35:26 -07001851 res.jsonValue["Storage"] = {
1852 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08001853
Ed Tanouscc340dd2018-08-29 13:43:38 -07001854 // TODO Need to support ForceRestart.
1855 res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
1856 {"target",
Ed Tanous029573d2019-02-01 10:57:49 -08001857 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
Ed Tanouscc340dd2018-08-29 13:43:38 -07001858 {"ResetType@Redfish.AllowableValues",
Jason M. Billsd22c8392019-06-03 13:59:03 -07001859 {"On", "ForceOff", "ForceOn", "ForceRestart", "GracefulRestart",
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001860 "GracefulShutdown", "PowerCycle", "Nmi"}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001861
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001862 res.jsonValue["LogServices"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001863 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001864
Carol Wangd82a3ac2019-11-21 13:56:38 +08001865 res.jsonValue["Bios"] = {
1866 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
1867
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001868 res.jsonValue["Links"]["ManagedBy"] = {
1869 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
1870
1871 res.jsonValue["Status"] = {
1872 {"Health", "OK"},
1873 {"State", "Enabled"},
1874 };
Ed Tanousa0803ef2018-08-29 13:29:23 -07001875 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001876
James Feiste284a7c2019-11-20 16:20:23 -08001877 constexpr const std::array<const char *, 4> inventoryForSystems = {
James Feistb49ac872019-05-21 15:12:01 -07001878 "xyz.openbmc_project.Inventory.Item.Dimm",
James Feist2ad9c2f2019-10-29 16:26:48 -07001879 "xyz.openbmc_project.Inventory.Item.Cpu",
James Feiste284a7c2019-11-20 16:20:23 -08001880 "xyz.openbmc_project.Inventory.Item.Drive",
1881 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07001882
1883 auto health = std::make_shared<HealthPopulate>(asyncResp);
1884 crow::connections::systemBus->async_method_call(
1885 [health](const boost::system::error_code ec,
1886 std::vector<std::string> &resp) {
1887 if (ec)
1888 {
1889 // no inventory
1890 return;
1891 }
1892
1893 health->inventory = std::move(resp);
1894 },
1895 "xyz.openbmc_project.ObjectMapper",
1896 "/xyz/openbmc_project/object_mapper",
1897 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
1898 int32_t(0), inventoryForSystems);
1899
1900 health->populate();
1901
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001902 getMainChassisId(asyncResp, [](const std::string &chassisId,
1903 std::shared_ptr<AsyncResp> aRsp) {
1904 aRsp->res.jsonValue["Links"]["Chassis"] = {
1905 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
1906 });
AppaRao Pulia3002222019-11-12 21:32:59 +05301907
1908 getIndicatorLedState(asyncResp);
James Feist5bc2dc82019-10-22 14:33:16 -07001909 getComputerSystem(asyncResp, health);
Ed Tanous6c34de42018-08-29 13:37:36 -07001910 getHostState(asyncResp);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301911 getBootProperties(asyncResp);
Jason M. Billsadbe1922019-10-14 15:44:35 -07001912 getPCIeDeviceList(asyncResp, "PCIeDevices");
Yong Li51709ff2019-09-30 14:13:04 +08001913 getHostWatchdogTimer(asyncResp);
George Liuc6a620f2020-04-10 17:18:11 +08001914 getPowerRestorePolicy(asyncResp);
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001915 getAutomaticRetry(asyncResp);
AppaRao Pulia6349912019-10-18 17:16:08 +05301916#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1917 getProvisioningStatus(asyncResp);
1918#endif
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001919 }
1920
Ed Tanous1abe55e2018-09-05 08:30:59 -07001921 void doPatch(crow::Response &res, const crow::Request &req,
1922 const std::vector<std::string> &params) override
1923 {
Santosh Puranikcde19e52019-02-20 00:10:56 +05301924 std::optional<std::string> indicatorLed;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301925 std::optional<nlohmann::json> bootProps;
Yong Lic45f0082019-10-10 14:19:01 +08001926 std::optional<nlohmann::json> wdtTimerProps;
George Liuc6a620f2020-04-10 17:18:11 +08001927 std::optional<std::string> powerRestorePolicy;
Santosh Puranik41352c22019-07-03 05:35:49 -05001928 auto asyncResp = std::make_shared<AsyncResp>(res);
1929
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001930 if (!json_util::readJson(req, res, "IndicatorLED", indicatorLed, "Boot",
George Liuc6a620f2020-04-10 17:18:11 +08001931 bootProps, "WatchdogTimer", wdtTimerProps,
1932 "PowerRestorePolicy", powerRestorePolicy))
Ed Tanous66173382018-08-15 18:20:59 -07001933 {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001934 return;
1935 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301936
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001937 res.result(boost::beast::http::status::no_content);
Yong Lic45f0082019-10-10 14:19:01 +08001938
1939 if (wdtTimerProps)
1940 {
1941 std::optional<bool> wdtEnable;
1942 std::optional<std::string> wdtTimeOutAction;
1943
1944 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
1945 "FunctionEnabled", wdtEnable,
1946 "TimeoutAction", wdtTimeOutAction))
1947 {
1948 return;
1949 }
1950 setWDTProperties(asyncResp, std::move(wdtEnable),
1951 std::move(wdtTimeOutAction));
1952 }
1953
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301954 if (bootProps)
1955 {
1956 std::optional<std::string> bootSource;
1957 std::optional<std::string> bootEnable;
Gunnar Mills69f35302020-05-17 16:06:31 -05001958 std::optional<std::string> automaticRetryConfig;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301959
Gunnar Mills69f35302020-05-17 16:06:31 -05001960 if (!json_util::readJson(
1961 *bootProps, asyncResp->res, "BootSourceOverrideTarget",
1962 bootSource, "BootSourceOverrideEnabled", bootEnable,
1963 "AutomaticRetryConfig", automaticRetryConfig))
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301964 {
1965 return;
1966 }
Gunnar Mills69f35302020-05-17 16:06:31 -05001967 if (bootSource || bootEnable)
1968 {
1969 setBootSourceProperties(asyncResp, std::move(bootSource),
1970 std::move(bootEnable));
1971 }
1972 if (automaticRetryConfig)
1973 {
1974 setAutomaticRetry(asyncResp, std::move(*automaticRetryConfig));
1975 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301976 }
Johnathan Mantey265c1602019-08-08 11:02:51 -07001977
Ed Tanous9712f8a2018-09-21 13:38:49 -07001978 if (indicatorLed)
1979 {
AppaRao Pulia3002222019-11-12 21:32:59 +05301980 setIndicatorLedState(asyncResp, std::move(*indicatorLed));
Ed Tanous1abe55e2018-09-05 08:30:59 -07001981 }
George Liuc6a620f2020-04-10 17:18:11 +08001982
1983 if (powerRestorePolicy)
1984 {
1985 setPowerRestorePolicy(asyncResp, std::move(*powerRestorePolicy));
1986 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001987 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001988};
Ed Tanous1abe55e2018-09-05 08:30:59 -07001989} // namespace redfish