blob: 0e2e52dbda707efba51458d12bedf11662810edb [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
Alpana Kumari9d3ae102019-04-12 06:49:32 -050031/**
32 * @brief Updates the Functional State of DIMMs
33 *
34 * @param[in] aResp Shared pointer for completing asynchronous calls
35 * @param[in] dimmState Dimm's Functional state, true/false
36 *
37 * @return None.
38 */
39void updateDimmProperties(std::shared_ptr<AsyncResp> aResp,
40 const std::variant<bool> &dimmState)
41{
42 const bool *isDimmFunctional = std::get_if<bool>(&dimmState);
43 if (isDimmFunctional == nullptr)
44 {
45 messages::internalError(aResp->res);
46 return;
47 }
Gunnar Mills698654b2019-10-16 13:17:37 -050048 BMCWEB_LOG_DEBUG << "Dimm Functional: " << *isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050049
50 // Set it as Enabled if atleast one DIMM is functional
51 // Update STATE only if previous State was DISABLED and current Dimm is
52 // ENABLED.
53 nlohmann::json &prevMemSummary =
54 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
55 if (prevMemSummary == "Disabled")
56 {
57 if (*isDimmFunctional == true)
58 {
59 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
60 "Enabled";
61 }
62 }
63}
64
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050065/*
66 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
67 *
68 * @param[in] aResp Shared pointer for completing asynchronous calls
69 * @param[in] cpuPresenceState CPU present or not
70 *
71 * @return None.
72 */
73void modifyCpuPresenceState(std::shared_ptr<AsyncResp> aResp,
74 const std::variant<bool> &cpuPresenceState)
75{
76 const bool *isCpuPresent = std::get_if<bool>(&cpuPresenceState);
77
78 if (isCpuPresent == nullptr)
79 {
80 messages::internalError(aResp->res);
81 return;
82 }
Gunnar Mills698654b2019-10-16 13:17:37 -050083 BMCWEB_LOG_DEBUG << "Cpu Present: " << *isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050084
85 nlohmann::json &procCount =
86 aResp->res.jsonValue["ProcessorSummary"]["Count"];
87 if (*isCpuPresent == true)
88 {
89 procCount = procCount.get<int>() + 1;
90 }
91 aResp->res.jsonValue["ProcessorSummary"]["Count"] = procCount;
92}
93
94/*
95 * @brief Update "ProcessorSummary" "Status" "State" based on
96 * CPU Functional State
97 *
98 * @param[in] aResp Shared pointer for completing asynchronous calls
99 * @param[in] cpuFunctionalState is CPU functional true/false
100 *
101 * @return None.
102 */
103void modifyCpuFunctionalState(std::shared_ptr<AsyncResp> aResp,
104 const std::variant<bool> &cpuFunctionalState)
105{
106 const bool *isCpuFunctional = std::get_if<bool>(&cpuFunctionalState);
107
108 if (isCpuFunctional == nullptr)
109 {
110 messages::internalError(aResp->res);
111 return;
112 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500113 BMCWEB_LOG_DEBUG << "Cpu Functional: " << *isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500114
115 nlohmann::json &prevProcState =
116 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
117
118 // Set it as Enabled if atleast one CPU is functional
119 // Update STATE only if previous State was Non_Functional and current CPU is
120 // Functional.
121 if (prevProcState == "Disabled")
122 {
123 if (*isCpuFunctional == true)
124 {
125 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
126 "Enabled";
127 }
128 }
129}
130
131/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700132 * @brief Retrieves computer system properties over dbus
133 *
134 * @param[in] aResp Shared pointer for completing asynchronous calls
135 * @param[in] name Computer system name from request
136 *
137 * @return None.
138 */
James Feist5bc2dc82019-10-22 14:33:16 -0700139void getComputerSystem(std::shared_ptr<AsyncResp> aResp,
140 std::shared_ptr<HealthPopulate> systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700141{
Ed Tanous6c34de42018-08-29 13:37:36 -0700142 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500143
Ed Tanous6c34de42018-08-29 13:37:36 -0700144 crow::connections::systemBus->async_method_call(
James Feist5bc2dc82019-10-22 14:33:16 -0700145 [aResp, systemHealth](
Ed Tanous6c34de42018-08-29 13:37:36 -0700146 const boost::system::error_code ec,
147 const std::vector<std::pair<
148 std::string,
149 std::vector<std::pair<std::string, std::vector<std::string>>>>>
150 &subtree) {
151 if (ec)
152 {
153 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700154 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700155 return;
156 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700157 // Iterate over all retrieved ObjectPaths.
158 for (const std::pair<std::string,
159 std::vector<std::pair<
160 std::string, std::vector<std::string>>>>
161 &object : subtree)
162 {
163 const std::string &path = object.first;
164 BMCWEB_LOG_DEBUG << "Got path: " << path;
165 const std::vector<
166 std::pair<std::string, std::vector<std::string>>>
167 &connectionNames = object.second;
168 if (connectionNames.size() < 1)
169 {
170 continue;
171 }
Ed Tanous029573d2019-02-01 10:57:49 -0800172
James Feist5bc2dc82019-10-22 14:33:16 -0700173 auto memoryHealth = std::make_shared<HealthPopulate>(
174 aResp, aResp->res.jsonValue["MemorySummary"]["Status"]);
175
176 auto cpuHealth = std::make_shared<HealthPopulate>(
177 aResp, aResp->res.jsonValue["ProcessorSummary"]["Status"]);
178
179 systemHealth->children.emplace_back(memoryHealth);
180 systemHealth->children.emplace_back(cpuHealth);
181
Ed Tanous029573d2019-02-01 10:57:49 -0800182 // This is not system, so check if it's cpu, dimm, UUID or
183 // BiosVer
184 for (const auto &connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700185 {
Ed Tanous029573d2019-02-01 10:57:49 -0800186 for (const auto &interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700187 {
Ed Tanous029573d2019-02-01 10:57:49 -0800188 if (interfaceName ==
189 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700190 {
Ed Tanous029573d2019-02-01 10:57:49 -0800191 BMCWEB_LOG_DEBUG
192 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500193
Ed Tanous029573d2019-02-01 10:57:49 -0800194 crow::connections::systemBus->async_method_call(
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500195 [aResp, service{connection.first},
196 path(std::move(path))](
197 const boost::system::error_code ec,
198 const std::vector<
199 std::pair<std::string, VariantType>>
200 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800201 if (ec)
202 {
203 BMCWEB_LOG_ERROR
204 << "DBUS response error " << ec;
205 messages::internalError(aResp->res);
206 return;
207 }
208 BMCWEB_LOG_DEBUG << "Got "
209 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500210 << " Dimm properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500211
212 if (properties.size() > 0)
Ed Tanous029573d2019-02-01 10:57:49 -0800213 {
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500214 for (const std::pair<std::string,
215 VariantType>
216 &property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700217 {
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500218 if (property.first ==
219 "MemorySizeInKb")
Ed Tanous6c34de42018-08-29 13:37:36 -0700220 {
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500221 const uint64_t *value =
222 sdbusplus::message::
223 variant_ns::get_if<
224 uint64_t>(
225 &property.second);
226 if (value != nullptr)
227 {
228 aResp->res.jsonValue
229 ["TotalSystemMemoryGi"
230 "B"] +=
231 *value / (1024 * 1024);
232 aResp->res.jsonValue
233 ["MemorySummary"]
234 ["Status"]["State"] =
235 "Enabled";
236 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700237 }
238 }
Ed Tanous029573d2019-02-01 10:57:49 -0800239 }
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500240 else
241 {
242 auto getDimmProperties =
243 [aResp](
244 const boost::system::error_code
245 ec,
246 const std::variant<bool>
247 &dimmState) {
248 if (ec)
249 {
250 BMCWEB_LOG_ERROR
251 << "DBUS response "
252 "error "
253 << ec;
254 return;
255 }
256 updateDimmProperties(aResp,
257 dimmState);
258 };
259 crow::connections::systemBus
260 ->async_method_call(
261 std::move(getDimmProperties),
262 service, path,
263 "org.freedesktop.DBus."
264 "Properties",
265 "Get",
266 "xyz.openbmc_project.State."
267 "Decorator.OperationalStatus",
268 "Functional");
269 }
Ed Tanous029573d2019-02-01 10:57:49 -0800270 },
271 connection.first, path,
272 "org.freedesktop.DBus.Properties", "GetAll",
273 "xyz.openbmc_project.Inventory.Item.Dimm");
James Feist5bc2dc82019-10-22 14:33:16 -0700274
275 memoryHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800276 }
277 else if (interfaceName ==
278 "xyz.openbmc_project.Inventory.Item.Cpu")
279 {
280 BMCWEB_LOG_DEBUG
281 << "Found Cpu, now get its properties.";
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500282
Ed Tanous029573d2019-02-01 10:57:49 -0800283 crow::connections::systemBus->async_method_call(
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500284 [aResp, service{connection.first},
285 path(std::move(path))](
286 const boost::system::error_code ec,
287 const std::vector<
288 std::pair<std::string, VariantType>>
289 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800290 if (ec)
291 {
292 BMCWEB_LOG_ERROR
293 << "DBUS response error " << ec;
294 messages::internalError(aResp->res);
295 return;
296 }
297 BMCWEB_LOG_DEBUG << "Got "
298 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500299 << " Cpu properties.";
Ed Tanous04a258f2018-10-15 08:00:41 -0700300
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500301 if (properties.size() > 0)
302 {
303 for (const auto &property : properties)
304 {
305 if (property.first ==
306 "ProcessorFamily")
307 {
308 const std::string *value =
309 sdbusplus::message::
310 variant_ns::get_if<
311 std::string>(
312 &property.second);
313 if (value != nullptr)
314 {
315 nlohmann::json
316 &procSummary =
317 aResp->res.jsonValue
318 ["ProcessorSumm"
319 "ary"];
320 nlohmann::json &procCount =
321 procSummary["Count"];
322 procCount =
323 procCount.get<int>() +
324 1;
325 procSummary["Status"]
326 ["State"] =
327 "Enabled";
328 procSummary["Model"] =
329 *value;
330 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700331 }
332 }
Ed Tanous029573d2019-02-01 10:57:49 -0800333 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500334 else
335 {
336 auto getCpuPresenceState =
337 [aResp](
338 const boost::system::error_code
339 ec,
340 const std::variant<bool>
341 &cpuPresenceCheck) {
342 if (ec)
343 {
344 BMCWEB_LOG_ERROR
345 << "DBUS response "
346 "error "
347 << ec;
348 return;
349 }
350 modifyCpuPresenceState(
351 aResp, cpuPresenceCheck);
352 };
353
354 auto getCpuFunctionalState =
355 [aResp](
356 const boost::system::error_code
357 ec,
358 const std::variant<bool>
359 &cpuFunctionalCheck) {
360 if (ec)
361 {
362 BMCWEB_LOG_ERROR
363 << "DBUS response "
364 "error "
365 << ec;
366 return;
367 }
368 modifyCpuFunctionalState(
369 aResp, cpuFunctionalCheck);
370 };
371 // Get the Presence of CPU
372 crow::connections::systemBus
373 ->async_method_call(
374 std::move(getCpuPresenceState),
375 service, path,
376 "org.freedesktop.DBus."
377 "Properties",
378 "Get",
379 "xyz.openbmc_project.Inventory."
380 "Item",
381 "Present");
382
383 // Get the Functional State
384 crow::connections::systemBus
385 ->async_method_call(
386 std::move(
387 getCpuFunctionalState),
388 service, path,
389 "org.freedesktop.DBus."
390 "Properties",
391 "Get",
392 "xyz.openbmc_project.State."
393 "Decorator."
394 "OperationalStatus",
395 "Functional");
396
397 // Get the MODEL from
398 // xyz.openbmc_project.Inventory.Decorator.Asset
399 // support it later as Model is Empty
400 // currently.
401 }
Ed Tanous029573d2019-02-01 10:57:49 -0800402 },
403 connection.first, path,
404 "org.freedesktop.DBus.Properties", "GetAll",
405 "xyz.openbmc_project.Inventory.Item.Cpu");
James Feist5bc2dc82019-10-22 14:33:16 -0700406
407 cpuHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800408 }
409 else if (interfaceName ==
410 "xyz.openbmc_project.Common.UUID")
411 {
412 BMCWEB_LOG_DEBUG
413 << "Found UUID, now get its properties.";
414 crow::connections::systemBus->async_method_call(
415 [aResp](const boost::system::error_code ec,
Ed Tanous6c34de42018-08-29 13:37:36 -0700416 const std::vector<
417 std::pair<std::string, VariantType>>
418 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800419 if (ec)
420 {
421 BMCWEB_LOG_DEBUG
422 << "DBUS response error " << ec;
423 messages::internalError(aResp->res);
424 return;
425 }
426 BMCWEB_LOG_DEBUG << "Got "
427 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500428 << " UUID properties.";
Ed Tanous029573d2019-02-01 10:57:49 -0800429 for (const std::pair<std::string,
430 VariantType>
431 &property : properties)
432 {
Ed Tanous029573d2019-02-01 10:57:49 -0800433 if (property.first == "UUID")
434 {
435 const std::string *value =
436 sdbusplus::message::variant_ns::
437 get_if<std::string>(
438 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700439
Ed Tanous029573d2019-02-01 10:57:49 -0800440 if (value != nullptr)
441 {
442 std::string valueStr = *value;
443 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700444 {
Ed Tanous029573d2019-02-01 10:57:49 -0800445 valueStr.insert(8, 1, '-');
446 valueStr.insert(13, 1, '-');
447 valueStr.insert(18, 1, '-');
448 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700449 }
Ed Tanous029573d2019-02-01 10:57:49 -0800450 BMCWEB_LOG_DEBUG << "UUID = "
451 << valueStr;
452 aResp->res.jsonValue["UUID"] =
453 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700454 }
455 }
Ed Tanous029573d2019-02-01 10:57:49 -0800456 }
457 },
458 connection.first, path,
459 "org.freedesktop.DBus.Properties", "GetAll",
460 "xyz.openbmc_project.Common.UUID");
461 }
462 else if (interfaceName ==
463 "xyz.openbmc_project.Inventory.Item.System")
464 {
465 crow::connections::systemBus->async_method_call(
466 [aResp](const boost::system::error_code ec,
467 const std::vector<
468 std::pair<std::string, VariantType>>
469 &propertiesList) {
470 if (ec)
471 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700472 // doesn't have to include this
473 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800474 return;
475 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500476 BMCWEB_LOG_DEBUG
477 << "Got " << propertiesList.size()
478 << " properties for system";
Ed Tanous029573d2019-02-01 10:57:49 -0800479 for (const std::pair<std::string,
480 VariantType>
481 &property : propertiesList)
482 {
beccabroekfc5afcf2019-03-05 14:35:15 -0600483 const std::string &propertyName =
484 property.first;
485 if ((propertyName == "PartNumber") ||
486 (propertyName == "SerialNumber") ||
487 (propertyName == "Manufacturer") ||
488 (propertyName == "Model"))
Ed Tanous029573d2019-02-01 10:57:49 -0800489 {
beccabroekfc5afcf2019-03-05 14:35:15 -0600490 const std::string *value =
491 std::get_if<std::string>(
492 &property.second);
493 if (value != nullptr)
494 {
495 aResp->res
496 .jsonValue[propertyName] =
497 *value;
498 }
Ed Tanous029573d2019-02-01 10:57:49 -0800499 }
500 }
501 aResp->res.jsonValue["Name"] = "system";
502 aResp->res.jsonValue["Id"] =
503 aResp->res.jsonValue["SerialNumber"];
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600504 // Grab the bios version
505 fw_util::getActiveFwVersion(
506 aResp, fw_util::biosPurpose,
507 "BiosVersion");
Ed Tanous029573d2019-02-01 10:57:49 -0800508 },
509 connection.first, path,
510 "org.freedesktop.DBus.Properties", "GetAll",
511 "xyz.openbmc_project.Inventory.Decorator."
512 "Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700513
514 crow::connections::systemBus->async_method_call(
515 [aResp](
516 const boost::system::error_code ec,
517 const std::variant<std::string> &property) {
518 if (ec)
519 {
520 // doesn't have to include this
521 // interface
522 return;
523 }
524
525 const std::string *value =
526 std::get_if<std::string>(&property);
527 if (value != nullptr)
528 {
529 aResp->res.jsonValue["AssetTag"] =
530 *value;
531 }
532 },
533 connection.first, path,
534 "org.freedesktop.DBus.Properties", "Get",
535 "xyz.openbmc_project.Inventory.Decorator."
536 "AssetTag",
537 "AssetTag");
Ed Tanous6c34de42018-08-29 13:37:36 -0700538 }
539 }
540 }
541 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700542 },
543 "xyz.openbmc_project.ObjectMapper",
544 "/xyz/openbmc_project/object_mapper",
545 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700546 "/xyz/openbmc_project/inventory", int32_t(0),
547 std::array<const char *, 5>{
548 "xyz.openbmc_project.Inventory.Decorator.Asset",
549 "xyz.openbmc_project.Inventory.Item.Cpu",
550 "xyz.openbmc_project.Inventory.Item.Dimm",
551 "xyz.openbmc_project.Inventory.Item.System",
552 "xyz.openbmc_project.Common.UUID",
553 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700554}
555
556/**
557 * @brief Retrieves identify led group properties over dbus
558 *
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530559 * @param[in] aResp Shared pointer for generating response message.
Ed Tanous6c34de42018-08-29 13:37:36 -0700560 * @param[in] callback Callback for process retrieved data.
561 *
562 * @return None.
563 */
564template <typename CallbackFunc>
565void getLedGroupIdentify(std::shared_ptr<AsyncResp> aResp,
566 CallbackFunc &&callback)
567{
568 BMCWEB_LOG_DEBUG << "Get led groups";
569 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800570 [aResp,
Ed Tanous66173382018-08-15 18:20:59 -0700571 callback{std::move(callback)}](const boost::system::error_code &ec,
572 const ManagedObjectsType &resp) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700573 if (ec)
574 {
575 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700576 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700577 return;
578 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500579 BMCWEB_LOG_DEBUG << "Got " << resp.size() << " led group objects.";
Ed Tanous6c34de42018-08-29 13:37:36 -0700580 for (const auto &objPath : resp)
581 {
582 const std::string &path = objPath.first;
583 if (path.rfind("enclosure_identify") != std::string::npos)
584 {
585 for (const auto &interface : objPath.second)
586 {
587 if (interface.first == "xyz.openbmc_project.Led.Group")
588 {
589 for (const auto &property : interface.second)
590 {
591 if (property.first == "Asserted")
592 {
593 const bool *asserted =
Ed Tanousabf2add2019-01-22 16:40:12 -0800594 std::get_if<bool>(&property.second);
Ed Tanous6c34de42018-08-29 13:37:36 -0700595 if (nullptr != asserted)
596 {
597 callback(*asserted, aResp);
598 }
599 else
600 {
601 callback(false, aResp);
602 }
603 }
604 }
605 }
606 }
607 }
608 }
609 },
610 "xyz.openbmc_project.LED.GroupManager",
611 "/xyz/openbmc_project/led/groups", "org.freedesktop.DBus.ObjectManager",
612 "GetManagedObjects");
613}
614
615template <typename CallbackFunc>
616void getLedIdentify(std::shared_ptr<AsyncResp> aResp, CallbackFunc &&callback)
617{
618 BMCWEB_LOG_DEBUG << "Get identify led properties";
619 crow::connections::systemBus->async_method_call(
Ed Tanous66173382018-08-15 18:20:59 -0700620 [aResp,
621 callback{std::move(callback)}](const boost::system::error_code ec,
622 const PropertiesType &properties) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700623 if (ec)
624 {
625 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700626 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700627 return;
628 }
629 BMCWEB_LOG_DEBUG << "Got " << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500630 << " led properties.";
Ed Tanous6c34de42018-08-29 13:37:36 -0700631 std::string output;
632 for (const auto &property : properties)
633 {
634 if (property.first == "State")
635 {
636 const std::string *s =
Ed Tanousabf2add2019-01-22 16:40:12 -0800637 std::get_if<std::string>(&property.second);
Ed Tanous6c34de42018-08-29 13:37:36 -0700638 if (nullptr != s)
639 {
640 BMCWEB_LOG_DEBUG << "Identify Led State: " << *s;
641 const auto pos = s->rfind('.');
642 if (pos != std::string::npos)
643 {
644 auto led = s->substr(pos + 1);
645 for (const std::pair<const char *, const char *>
646 &p :
647 std::array<
648 std::pair<const char *, const char *>, 3>{
649 {{"On", "Lit"},
650 {"Blink", "Blinking"},
651 {"Off", "Off"}}})
652 {
653 if (led == p.first)
654 {
655 output = p.second;
656 }
657 }
658 }
659 }
660 }
661 }
662 callback(output, aResp);
663 },
664 "xyz.openbmc_project.LED.Controller.identify",
665 "/xyz/openbmc_project/led/physical/identify",
666 "org.freedesktop.DBus.Properties", "GetAll",
667 "xyz.openbmc_project.Led.Physical");
668}
Ed Tanous6c34de42018-08-29 13:37:36 -0700669/**
670 * @brief Retrieves host state properties over dbus
671 *
672 * @param[in] aResp Shared pointer for completing asynchronous calls.
673 *
674 * @return None.
675 */
676void getHostState(std::shared_ptr<AsyncResp> aResp)
677{
678 BMCWEB_LOG_DEBUG << "Get host information.";
679 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800680 [aResp](const boost::system::error_code ec,
681 const std::variant<std::string> &hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700682 if (ec)
683 {
684 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700685 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700686 return;
687 }
Ed Tanous66173382018-08-15 18:20:59 -0700688
Ed Tanousabf2add2019-01-22 16:40:12 -0800689 const std::string *s = std::get_if<std::string>(&hostState);
Ed Tanous66173382018-08-15 18:20:59 -0700690 BMCWEB_LOG_DEBUG << "Host state: " << *s;
691 if (s != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700692 {
Ed Tanous66173382018-08-15 18:20:59 -0700693 // Verify Host State
Andrew Geissler94732662019-01-08 19:32:16 -0800694 if (*s == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700695 {
Ed Tanous66173382018-08-15 18:20:59 -0700696 aResp->res.jsonValue["PowerState"] = "On";
697 aResp->res.jsonValue["Status"]["State"] = "Enabled";
698 }
699 else
700 {
701 aResp->res.jsonValue["PowerState"] = "Off";
702 aResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700703 }
704 }
705 },
706 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Ed Tanous66173382018-08-15 18:20:59 -0700707 "org.freedesktop.DBus.Properties", "Get",
708 "xyz.openbmc_project.State.Host", "CurrentHostState");
Ed Tanous6c34de42018-08-29 13:37:36 -0700709}
710
711/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530712 * @brief Traslates boot source DBUS property value to redfish.
713 *
714 * @param[in] dbusSource The boot source in DBUS speak.
715 *
716 * @return Returns as a string, the boot source in Redfish terms. If translation
717 * cannot be done, returns an empty string.
718 */
719static std::string dbusToRfBootSource(const std::string &dbusSource)
720{
721 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
722 {
723 return "None";
724 }
725 else if (dbusSource ==
726 "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
727 {
728 return "Hdd";
729 }
730 else if (dbusSource ==
Santosh Puranika71dc0b2019-05-23 20:10:49 +0530731 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530732 {
733 return "Cd";
734 }
735 else if (dbusSource ==
736 "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
737 {
738 return "Pxe";
739 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700740 else if (dbusSource ==
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700741 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700742 {
743 return "Usb";
744 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530745 else
746 {
747 return "";
748 }
749}
750
751/**
752 * @brief Traslates boot mode DBUS property value to redfish.
753 *
754 * @param[in] dbusMode The boot mode in DBUS speak.
755 *
756 * @return Returns as a string, the boot mode in Redfish terms. If translation
757 * cannot be done, returns an empty string.
758 */
759static std::string dbusToRfBootMode(const std::string &dbusMode)
760{
761 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
762 {
763 return "None";
764 }
765 else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
766 {
767 return "Diags";
768 }
769 else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
770 {
771 return "BiosSetup";
772 }
773 else
774 {
775 return "";
776 }
777}
778
779/**
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700780 * @brief Traslates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530781 *
782 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700783 * @param[out] bootSource The DBus source
784 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530785 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700786 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530787 */
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700788static int assignBootParameters(std::shared_ptr<AsyncResp> aResp,
789 const std::string &rfSource,
790 std::string &bootSource, std::string &bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530791{
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700792 // The caller has initialized the bootSource and bootMode to:
793 // bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
794 // bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
795 // Only modify the bootSource/bootMode variable needed to achieve the
796 // desired boot action.
797
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530798 if (rfSource == "None")
799 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700800 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530801 }
802 else if (rfSource == "Pxe")
803 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700804 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
805 }
806 else if (rfSource == "Hdd")
807 {
808 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
809 }
810 else if (rfSource == "Diags")
811 {
812 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
813 }
814 else if (rfSource == "Cd")
815 {
816 bootSource =
817 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
818 }
819 else if (rfSource == "BiosSetup")
820 {
821 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530822 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700823 else if (rfSource == "Usb")
824 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700825 bootSource =
826 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700827 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530828 else
829 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700830 BMCWEB_LOG_DEBUG << "Invalid property value for "
831 "BootSourceOverrideTarget: "
832 << bootSource;
833 messages::propertyValueNotInList(aResp->res, rfSource,
834 "BootSourceTargetOverride");
835 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530836 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700837 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530838}
839
840/**
841 * @brief Retrieves boot mode over DBUS and fills out the response
842 *
843 * @param[in] aResp Shared pointer for generating response message.
844 * @param[in] bootDbusObj The dbus object to query for boot properties.
845 *
846 * @return None.
847 */
848static void getBootMode(std::shared_ptr<AsyncResp> aResp,
849 std::string bootDbusObj)
850{
851 crow::connections::systemBus->async_method_call(
852 [aResp](const boost::system::error_code ec,
853 const std::variant<std::string> &bootMode) {
854 if (ec)
855 {
856 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
857 messages::internalError(aResp->res);
858 return;
859 }
860
861 const std::string *bootModeStr =
862 std::get_if<std::string>(&bootMode);
863
864 if (!bootModeStr)
865 {
866 messages::internalError(aResp->res);
867 return;
868 }
869
870 BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
871
872 // TODO (Santosh): Do we need to support override mode?
873 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = "Legacy";
874 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
875 "AllowableValues"] = {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700876 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530877
878 if (*bootModeStr !=
879 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
880 {
881 auto rfMode = dbusToRfBootMode(*bootModeStr);
882 if (!rfMode.empty())
883 {
884 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
885 rfMode;
886 }
887 }
888
889 // If the BootSourceOverrideTarget is still "None" at the end,
890 // reset the BootSourceOverrideEnabled to indicate that
891 // overrides are disabled
892 if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] ==
893 "None")
894 {
895 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
896 "Disabled";
897 }
898 },
899 "xyz.openbmc_project.Settings", bootDbusObj,
900 "org.freedesktop.DBus.Properties", "Get",
901 "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
902}
903
904/**
905 * @brief Retrieves boot source over DBUS
906 *
907 * @param[in] aResp Shared pointer for generating response message.
908 * @param[in] oneTimeEnable Boolean to indicate boot properties are one-time.
909 *
910 * @return None.
911 */
912static void getBootSource(std::shared_ptr<AsyncResp> aResp, bool oneTimeEnabled)
913{
914 std::string bootDbusObj =
915 oneTimeEnabled ? "/xyz/openbmc_project/control/host0/boot/one_time"
916 : "/xyz/openbmc_project/control/host0/boot";
917
918 BMCWEB_LOG_DEBUG << "Is one time: " << oneTimeEnabled;
919 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
920 (oneTimeEnabled) ? "Once" : "Continuous";
921
922 crow::connections::systemBus->async_method_call(
923 [aResp, bootDbusObj](const boost::system::error_code ec,
924 const std::variant<std::string> &bootSource) {
925 if (ec)
926 {
927 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
928 messages::internalError(aResp->res);
929 return;
930 }
931
932 const std::string *bootSourceStr =
933 std::get_if<std::string>(&bootSource);
934
935 if (!bootSourceStr)
936 {
937 messages::internalError(aResp->res);
938 return;
939 }
940 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
941
942 auto rfSource = dbusToRfBootSource(*bootSourceStr);
943 if (!rfSource.empty())
944 {
945 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
946 rfSource;
947 }
948 },
949 "xyz.openbmc_project.Settings", bootDbusObj,
950 "org.freedesktop.DBus.Properties", "Get",
951 "xyz.openbmc_project.Control.Boot.Source", "BootSource");
952 getBootMode(std::move(aResp), std::move(bootDbusObj));
953}
954
955/**
956 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
957 * get boot source and boot mode.
958 *
959 * @param[in] aResp Shared pointer for generating response message.
960 *
961 * @return None.
962 */
963static void getBootProperties(std::shared_ptr<AsyncResp> aResp)
964{
965 BMCWEB_LOG_DEBUG << "Get boot information.";
966
967 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800968 [aResp](const boost::system::error_code ec,
969 const sdbusplus::message::variant<bool> &oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530970 if (ec)
971 {
972 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
James Feist2a833c72019-07-19 10:17:13 -0700973 // not an error, don't have to have the interface
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530974 return;
975 }
976
977 const bool *oneTimePtr = std::get_if<bool>(&oneTime);
978
979 if (!oneTimePtr)
980 {
981 messages::internalError(aResp->res);
982 return;
983 }
984 getBootSource(aResp, *oneTimePtr);
985 },
986 "xyz.openbmc_project.Settings",
987 "/xyz/openbmc_project/control/host0/boot/one_time",
988 "org.freedesktop.DBus.Properties", "Get",
989 "xyz.openbmc_project.Object.Enable", "Enabled");
990}
991
992/**
993 * @brief Sets boot properties into DBUS object(s).
994 *
995 * @param[in] aResp Shared pointer for generating response message.
996 * @param[in] oneTimeEnabled Is "one-time" setting already enabled.
997 * @param[in] bootSource The boot source to set.
998 * @param[in] bootEnable The source override "enable" to set.
999 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001000 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301001 */
1002static void setBootModeOrSource(std::shared_ptr<AsyncResp> aResp,
1003 bool oneTimeEnabled,
1004 std::optional<std::string> bootSource,
1005 std::optional<std::string> bootEnable)
1006{
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001007 std::string bootSourceStr =
1008 "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
1009 std::string bootModeStr =
1010 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301011 bool oneTimeSetting = oneTimeEnabled;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001012 bool useBootSource = true;
1013
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301014 // Validate incoming parameters
1015 if (bootEnable)
1016 {
1017 if (*bootEnable == "Once")
1018 {
1019 oneTimeSetting = true;
1020 }
1021 else if (*bootEnable == "Continuous")
1022 {
1023 oneTimeSetting = false;
1024 }
1025 else if (*bootEnable == "Disabled")
1026 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001027 BMCWEB_LOG_DEBUG << "Boot source override will be disabled";
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301028 oneTimeSetting = false;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001029 useBootSource = false;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301030 }
1031 else
1032 {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301033 BMCWEB_LOG_DEBUG << "Unsupported value for "
1034 "BootSourceOverrideEnabled: "
1035 << *bootEnable;
1036 messages::propertyValueNotInList(aResp->res, *bootEnable,
1037 "BootSourceOverrideEnabled");
1038 return;
1039 }
1040 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301041
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001042 if (bootSource && useBootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301043 {
1044 // Source target specified
1045 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1046 // Figure out which DBUS interface and property to use
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001047 if (assignBootParameters(aResp, *bootSource, bootSourceStr,
1048 bootModeStr))
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301049 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001050 BMCWEB_LOG_DEBUG
1051 << "Invalid property value for BootSourceOverrideTarget: "
1052 << *bootSource;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301053 messages::propertyValueNotInList(aResp->res, *bootSource,
1054 "BootSourceTargetOverride");
1055 return;
1056 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001057 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301058
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001059 // Act on validated parameters
1060 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1061 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
1062 const char *bootObj =
1063 oneTimeSetting ? "/xyz/openbmc_project/control/host0/boot/one_time"
1064 : "/xyz/openbmc_project/control/host0/boot";
1065
1066 crow::connections::systemBus->async_method_call(
1067 [aResp](const boost::system::error_code ec) {
1068 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301069 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001070 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1071 messages::internalError(aResp->res);
1072 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301073 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001074 BMCWEB_LOG_DEBUG << "Boot source update done.";
1075 },
1076 "xyz.openbmc_project.Settings", bootObj,
1077 "org.freedesktop.DBus.Properties", "Set",
1078 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1079 std::variant<std::string>(bootSourceStr));
1080
1081 crow::connections::systemBus->async_method_call(
1082 [aResp](const boost::system::error_code ec) {
1083 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301084 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001085 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1086 messages::internalError(aResp->res);
1087 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301088 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001089 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1090 },
1091 "xyz.openbmc_project.Settings", bootObj,
1092 "org.freedesktop.DBus.Properties", "Set",
1093 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1094 std::variant<std::string>(bootModeStr));
1095
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301096 crow::connections::systemBus->async_method_call(
1097 [aResp{std::move(aResp)}](const boost::system::error_code ec) {
1098 if (ec)
1099 {
1100 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1101 messages::internalError(aResp->res);
1102 return;
1103 }
1104 BMCWEB_LOG_DEBUG << "Boot enable update done.";
1105 },
1106 "xyz.openbmc_project.Settings",
1107 "/xyz/openbmc_project/control/host0/boot/one_time",
1108 "org.freedesktop.DBus.Properties", "Set",
1109 "xyz.openbmc_project.Object.Enable", "Enabled",
1110 std::variant<bool>(oneTimeSetting));
1111}
1112
1113/**
1114 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
1115 * set boot source/boot mode properties.
1116 *
1117 * @param[in] aResp Shared pointer for generating response message.
1118 * @param[in] bootSource The boot source from incoming RF request.
1119 * @param[in] bootEnable The boot override enable from incoming RF request.
1120 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001121 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301122 */
1123static void setBootProperties(std::shared_ptr<AsyncResp> aResp,
1124 std::optional<std::string> bootSource,
1125 std::optional<std::string> bootEnable)
1126{
1127 BMCWEB_LOG_DEBUG << "Set boot information.";
1128
1129 crow::connections::systemBus->async_method_call(
Johnathan Mantey265c1602019-08-08 11:02:51 -07001130 [aResp, bootSource{std::move(bootSource)},
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301131 bootEnable{std::move(bootEnable)}](
1132 const boost::system::error_code ec,
1133 const sdbusplus::message::variant<bool> &oneTime) {
1134 if (ec)
1135 {
1136 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1137 messages::internalError(aResp->res);
1138 return;
1139 }
1140
1141 const bool *oneTimePtr = std::get_if<bool>(&oneTime);
1142
1143 if (!oneTimePtr)
1144 {
1145 messages::internalError(aResp->res);
1146 return;
1147 }
1148
1149 BMCWEB_LOG_DEBUG << "Got one time: " << *oneTimePtr;
1150
1151 setBootModeOrSource(aResp, *oneTimePtr, std::move(bootSource),
1152 std::move(bootEnable));
1153 },
1154 "xyz.openbmc_project.Settings",
1155 "/xyz/openbmc_project/control/host0/boot/one_time",
1156 "org.freedesktop.DBus.Properties", "Get",
1157 "xyz.openbmc_project.Object.Enable", "Enabled");
1158}
1159
1160/**
Yong Li51709ff2019-09-30 14:13:04 +08001161 * @brief Translates watchdog timeout action DBUS property value to redfish.
1162 *
1163 * @param[in] dbusAction The watchdog timeout action in D-BUS.
1164 *
1165 * @return Returns as a string, the timeout action in Redfish terms. If
1166 * translation cannot be done, returns an empty string.
1167 */
1168static std::string dbusToRfWatchdogAction(const std::string &dbusAction)
1169{
1170 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
1171 {
1172 return "None";
1173 }
1174 else if (dbusAction ==
1175 "xyz.openbmc_project.State.Watchdog.Action.HardReset")
1176 {
1177 return "ResetSystem";
1178 }
1179 else if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
1180 {
1181 return "PowerDown";
1182 }
1183 else if (dbusAction ==
1184 "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
1185 {
1186 return "PowerCycle";
1187 }
1188
1189 return "";
1190}
1191
1192/**
Yong Lic45f0082019-10-10 14:19:01 +08001193 *@brief Translates timeout action from Redfish to DBUS property value.
1194 *
1195 *@param[in] rfAction The timeout action in Redfish.
1196 *
1197 *@return Returns as a string, the time_out action as expected by DBUS.
1198 *If translation cannot be done, returns an empty string.
1199 */
1200
1201static std::string rfToDbusWDTTimeOutAct(const std::string &rfAction)
1202{
1203 if (rfAction == "None")
1204 {
1205 return "xyz.openbmc_project.State.Watchdog.Action.None";
1206 }
1207 else if (rfAction == "PowerCycle")
1208 {
1209 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
1210 }
1211 else if (rfAction == "PowerDown")
1212 {
1213 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
1214 }
1215 else if (rfAction == "ResetSystem")
1216 {
1217 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
1218 }
1219
1220 return "";
1221}
1222
1223/**
Yong Li51709ff2019-09-30 14:13:04 +08001224 * @brief Retrieves host watchdog timer properties over DBUS
1225 *
1226 * @param[in] aResp Shared pointer for completing asynchronous calls.
1227 *
1228 * @return None.
1229 */
1230void getHostWatchdogTimer(std::shared_ptr<AsyncResp> aResp)
1231{
1232 BMCWEB_LOG_DEBUG << "Get host watchodg";
1233 crow::connections::systemBus->async_method_call(
1234 [aResp](const boost::system::error_code ec,
1235 PropertiesType &properties) {
1236 if (ec)
1237 {
1238 // watchdog service is stopped
1239 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1240 return;
1241 }
1242
1243 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
1244
1245 nlohmann::json &hostWatchdogTimer =
1246 aResp->res.jsonValue["HostWatchdogTimer"];
1247
1248 // watchdog service is running/enabled
1249 hostWatchdogTimer["Status"]["State"] = "Enabled";
1250
1251 for (const auto &property : properties)
1252 {
1253 BMCWEB_LOG_DEBUG << "prop=" << property.first;
1254 if (property.first == "Enabled")
1255 {
1256 const bool *state = std::get_if<bool>(&property.second);
1257
1258 if (!state)
1259 {
1260 messages::internalError(aResp->res);
1261 continue;
1262 }
1263
1264 hostWatchdogTimer["FunctionEnabled"] = *state;
1265 }
1266 else if (property.first == "ExpireAction")
1267 {
1268 const std::string *s =
1269 std::get_if<std::string>(&property.second);
1270 if (!s)
1271 {
1272 messages::internalError(aResp->res);
1273 continue;
1274 }
1275
1276 std::string action = dbusToRfWatchdogAction(*s);
1277 if (action.empty())
1278 {
1279 messages::internalError(aResp->res);
1280 continue;
1281 }
1282 hostWatchdogTimer["TimeoutAction"] = action;
1283 }
1284 }
1285 },
1286 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
1287 "org.freedesktop.DBus.Properties", "GetAll",
1288 "xyz.openbmc_project.State.Watchdog");
1289}
1290
1291/**
Yong Lic45f0082019-10-10 14:19:01 +08001292 * @brief Sets Host WatchDog Timer properties.
1293 *
1294 * @param[in] aResp Shared pointer for generating response message.
1295 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
1296 * RF request.
1297 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
1298 *
1299 * @return None.
1300 */
1301static void setWDTProperties(std::shared_ptr<AsyncResp> aResp,
1302 const std::optional<bool> wdtEnable,
1303 const std::optional<std::string> &wdtTimeOutAction)
1304{
1305 BMCWEB_LOG_DEBUG << "Set host watchdog";
1306
1307 if (wdtTimeOutAction)
1308 {
1309 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
1310 // check if TimeOut Action is Valid
1311 if (wdtTimeOutActStr.empty())
1312 {
1313 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
1314 << *wdtTimeOutAction;
1315 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
1316 "TimeoutAction");
1317 return;
1318 }
1319
1320 crow::connections::systemBus->async_method_call(
1321 [aResp](const boost::system::error_code ec) {
1322 if (ec)
1323 {
1324 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1325 messages::internalError(aResp->res);
1326 return;
1327 }
1328 },
1329 "xyz.openbmc_project.Watchdog",
1330 "/xyz/openbmc_project/watchdog/host0",
1331 "org.freedesktop.DBus.Properties", "Set",
1332 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
1333 std::variant<std::string>(wdtTimeOutActStr));
1334 }
1335
1336 if (wdtEnable)
1337 {
1338 crow::connections::systemBus->async_method_call(
1339 [aResp](const boost::system::error_code ec) {
1340 if (ec)
1341 {
1342 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1343 messages::internalError(aResp->res);
1344 return;
1345 }
1346 },
1347 "xyz.openbmc_project.Watchdog",
1348 "/xyz/openbmc_project/watchdog/host0",
1349 "org.freedesktop.DBus.Properties", "Set",
1350 "xyz.openbmc_project.State.Watchdog", "Enabled",
1351 std::variant<bool>(*wdtEnable));
1352 }
1353}
1354
1355/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001356 * SystemsCollection derived class for delivering ComputerSystems Collection
1357 * Schema
1358 */
Ed Tanous1abe55e2018-09-05 08:30:59 -07001359class SystemsCollection : public Node
1360{
1361 public:
1362 SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/")
1363 {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001364 entityPrivileges = {
1365 {boost::beast::http::verb::get, {{"Login"}}},
1366 {boost::beast::http::verb::head, {{"Login"}}},
1367 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1368 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1369 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1370 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1371 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001372
Ed Tanous1abe55e2018-09-05 08:30:59 -07001373 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -07001374 void doGet(crow::Response &res, const crow::Request &req,
1375 const std::vector<std::string> &params) override
1376 {
Ed Tanous0f74e642018-11-12 15:17:05 -08001377 res.jsonValue["@odata.type"] =
1378 "#ComputerSystemCollection.ComputerSystemCollection";
1379 res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
1380 res.jsonValue["@odata.context"] =
1381 "/redfish/v1/"
1382 "$metadata#ComputerSystemCollection.ComputerSystemCollection";
1383 res.jsonValue["Name"] = "Computer System Collection";
Ed Tanous029573d2019-02-01 10:57:49 -08001384 res.jsonValue["Members"] = {
1385 {{"@odata.id", "/redfish/v1/Systems/system"}}};
1386 res.jsonValue["Members@odata.count"] = 1;
1387 res.end();
Ed Tanous1abe55e2018-09-05 08:30:59 -07001388 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001389};
1390
1391/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07001392 * SystemActionsReset class supports handle POST method for Reset action.
1393 * The class retrieves and sends data directly to D-Bus.
1394 */
1395class SystemActionsReset : public Node
1396{
1397 public:
1398 SystemActionsReset(CrowApp &app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001399 Node(app, "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanouscc340dd2018-08-29 13:43:38 -07001400 {
1401 entityPrivileges = {
1402 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1403 }
1404
1405 private:
1406 /**
1407 * Function handles POST method request.
1408 * Analyzes POST body message before sends Reset request data to D-Bus.
1409 */
1410 void doPost(crow::Response &res, const crow::Request &req,
1411 const std::vector<std::string> &params) override
1412 {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001413 auto asyncResp = std::make_shared<AsyncResp>(res);
1414
1415 std::string resetType;
1416 if (!json_util::readJson(req, res, "ResetType", resetType))
Ed Tanouscc340dd2018-08-29 13:43:38 -07001417 {
1418 return;
1419 }
1420
Jason M. Billsd22c8392019-06-03 13:59:03 -07001421 // Get the command and host vs. chassis
Ed Tanous9712f8a2018-09-21 13:38:49 -07001422 std::string command;
Jason M. Billsd22c8392019-06-03 13:59:03 -07001423 bool hostCommand;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001424 if (resetType == "On")
1425 {
1426 command = "xyz.openbmc_project.State.Host.Transition.On";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001427 hostCommand = true;
1428 }
1429 else if (resetType == "ForceOff")
1430 {
1431 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
1432 hostCommand = false;
1433 }
1434 else if (resetType == "ForceOn")
1435 {
1436 command = "xyz.openbmc_project.State.Host.Transition.On";
1437 hostCommand = true;
1438 }
1439 else if (resetType == "ForceRestart")
1440 {
1441 command = "xyz.openbmc_project.State.Chassis.Transition.Reset";
1442 hostCommand = false;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001443 }
1444 else if (resetType == "GracefulShutdown")
1445 {
1446 command = "xyz.openbmc_project.State.Host.Transition.Off";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001447 hostCommand = true;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001448 }
1449 else if (resetType == "GracefulRestart")
1450 {
1451 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001452 hostCommand = true;
1453 }
1454 else if (resetType == "PowerCycle")
1455 {
1456 command = "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
1457 hostCommand = false;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001458 }
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001459 else if (resetType == "Nmi")
1460 {
1461 doNMI(asyncResp);
1462 return;
1463 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001464 else
1465 {
Jason M. Billsf12894f2018-10-09 12:45:45 -07001466 messages::actionParameterUnknown(res, "Reset", resetType);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001467 return;
1468 }
1469
Jason M. Billsd22c8392019-06-03 13:59:03 -07001470 if (hostCommand)
1471 {
1472 crow::connections::systemBus->async_method_call(
1473 [asyncResp, resetType](const boost::system::error_code ec) {
1474 if (ec)
1475 {
1476 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1477 if (ec.value() == boost::asio::error::invalid_argument)
1478 {
1479 messages::actionParameterNotSupported(
1480 asyncResp->res, resetType, "Reset");
1481 }
1482 else
1483 {
1484 messages::internalError(asyncResp->res);
1485 }
1486 return;
1487 }
1488 messages::success(asyncResp->res);
1489 },
1490 "xyz.openbmc_project.State.Host",
1491 "/xyz/openbmc_project/state/host0",
1492 "org.freedesktop.DBus.Properties", "Set",
1493 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
1494 std::variant<std::string>{command});
1495 }
1496 else
1497 {
1498 crow::connections::systemBus->async_method_call(
1499 [asyncResp, resetType](const boost::system::error_code ec) {
1500 if (ec)
1501 {
1502 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1503 if (ec.value() == boost::asio::error::invalid_argument)
1504 {
1505 messages::actionParameterNotSupported(
1506 asyncResp->res, resetType, "Reset");
1507 }
1508 else
1509 {
1510 messages::internalError(asyncResp->res);
1511 }
1512 return;
1513 }
1514 messages::success(asyncResp->res);
1515 },
1516 "xyz.openbmc_project.State.Chassis",
1517 "/xyz/openbmc_project/state/chassis0",
1518 "org.freedesktop.DBus.Properties", "Set",
1519 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
1520 std::variant<std::string>{command});
1521 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07001522 }
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001523 /**
1524 * Function transceives data with dbus directly.
1525 */
1526 void doNMI(const std::shared_ptr<AsyncResp> &asyncResp)
1527 {
1528 constexpr char const *serviceName =
1529 "xyz.openbmc_project.Control.Host.NMI";
1530 constexpr char const *objectPath =
1531 "/xyz/openbmc_project/control/host0/nmi";
1532 constexpr char const *interfaceName =
1533 "xyz.openbmc_project.Control.Host.NMI";
1534 constexpr char const *method = "NMI";
1535
1536 crow::connections::systemBus->async_method_call(
1537 [asyncResp](const boost::system::error_code ec) {
1538 if (ec)
1539 {
1540 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
1541 messages::internalError(asyncResp->res);
1542 return;
1543 }
1544 messages::success(asyncResp->res);
1545 },
1546 serviceName, objectPath, interfaceName, method);
1547 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07001548};
1549
1550/**
Ed Tanous66173382018-08-15 18:20:59 -07001551 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001552 */
Ed Tanous1abe55e2018-09-05 08:30:59 -07001553class Systems : public Node
1554{
1555 public:
1556 /*
1557 * Default Constructor
1558 */
Ed Tanous029573d2019-02-01 10:57:49 -08001559 Systems(CrowApp &app) : Node(app, "/redfish/v1/Systems/system/")
Ed Tanous1abe55e2018-09-05 08:30:59 -07001560 {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001561 entityPrivileges = {
1562 {boost::beast::http::verb::get, {{"Login"}}},
1563 {boost::beast::http::verb::head, {{"Login"}}},
1564 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1565 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1566 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1567 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001568 }
1569
Ed Tanous1abe55e2018-09-05 08:30:59 -07001570 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -07001571 /**
1572 * Functions triggers appropriate requests on DBus
1573 */
1574 void doGet(crow::Response &res, const crow::Request &req,
1575 const std::vector<std::string> &params) override
1576 {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301577 res.jsonValue["@odata.type"] = "#ComputerSystem.v1_6_0.ComputerSystem";
Ed Tanous0f74e642018-11-12 15:17:05 -08001578 res.jsonValue["@odata.context"] =
1579 "/redfish/v1/$metadata#ComputerSystem.ComputerSystem";
Ed Tanous029573d2019-02-01 10:57:49 -08001580 res.jsonValue["Name"] = "Computer System";
1581 res.jsonValue["Id"] = "system";
Ed Tanous0f74e642018-11-12 15:17:05 -08001582 res.jsonValue["SystemType"] = "Physical";
1583 res.jsonValue["Description"] = "Computer System";
Ed Tanous0f74e642018-11-12 15:17:05 -08001584 res.jsonValue["ProcessorSummary"]["Count"] = 0;
1585 res.jsonValue["ProcessorSummary"]["Status"]["State"] = "Disabled";
1586 res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] = int(0);
1587 res.jsonValue["MemorySummary"]["Status"]["State"] = "Disabled";
Ed Tanous029573d2019-02-01 10:57:49 -08001588 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07001589
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001590 res.jsonValue["Processors"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001591 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001592 res.jsonValue["Memory"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001593 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
Nikhil Potadea25aecc2019-08-23 16:35:26 -07001594 res.jsonValue["Storage"] = {
1595 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08001596
Ed Tanouscc340dd2018-08-29 13:43:38 -07001597 // TODO Need to support ForceRestart.
1598 res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
1599 {"target",
Ed Tanous029573d2019-02-01 10:57:49 -08001600 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
Ed Tanouscc340dd2018-08-29 13:43:38 -07001601 {"ResetType@Redfish.AllowableValues",
Jason M. Billsd22c8392019-06-03 13:59:03 -07001602 {"On", "ForceOff", "ForceOn", "ForceRestart", "GracefulRestart",
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001603 "GracefulShutdown", "PowerCycle", "Nmi"}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001604
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001605 res.jsonValue["LogServices"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001606 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001607
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001608 res.jsonValue["Links"]["ManagedBy"] = {
1609 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
1610
1611 res.jsonValue["Status"] = {
1612 {"Health", "OK"},
1613 {"State", "Enabled"},
1614 };
Ed Tanousa0803ef2018-08-29 13:29:23 -07001615 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001616
James Feistb49ac872019-05-21 15:12:01 -07001617 constexpr const std::array<const char *, 2> inventoryForSystems = {
1618 "xyz.openbmc_project.Inventory.Item.Dimm",
1619 "xyz.openbmc_project.Inventory.Item.Cpu"};
1620
1621 auto health = std::make_shared<HealthPopulate>(asyncResp);
1622 crow::connections::systemBus->async_method_call(
1623 [health](const boost::system::error_code ec,
1624 std::vector<std::string> &resp) {
1625 if (ec)
1626 {
1627 // no inventory
1628 return;
1629 }
1630
1631 health->inventory = std::move(resp);
1632 },
1633 "xyz.openbmc_project.ObjectMapper",
1634 "/xyz/openbmc_project/object_mapper",
1635 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
1636 int32_t(0), inventoryForSystems);
1637
1638 health->populate();
1639
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001640 getMainChassisId(asyncResp, [](const std::string &chassisId,
1641 std::shared_ptr<AsyncResp> aRsp) {
1642 aRsp->res.jsonValue["Links"]["Chassis"] = {
1643 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
1644 });
Ed Tanous6c34de42018-08-29 13:37:36 -07001645 getLedGroupIdentify(
Ed Tanousa0803ef2018-08-29 13:29:23 -07001646 asyncResp,
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001647 [](const bool &asserted, const std::shared_ptr<AsyncResp> aRsp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001648 if (asserted)
1649 {
1650 // If led group is asserted, then another call is needed to
1651 // get led status
Ed Tanous6c34de42018-08-29 13:37:36 -07001652 getLedIdentify(
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001653 aRsp, [](const std::string &ledStatus,
1654 const std::shared_ptr<AsyncResp> aRsp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001655 if (!ledStatus.empty())
1656 {
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001657 aRsp->res.jsonValue["IndicatorLED"] = ledStatus;
Ed Tanous1abe55e2018-09-05 08:30:59 -07001658 }
1659 });
1660 }
1661 else
1662 {
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001663 aRsp->res.jsonValue["IndicatorLED"] = "Off";
Ed Tanous1abe55e2018-09-05 08:30:59 -07001664 }
1665 });
James Feist5bc2dc82019-10-22 14:33:16 -07001666 getComputerSystem(asyncResp, health);
Ed Tanous6c34de42018-08-29 13:37:36 -07001667 getHostState(asyncResp);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301668 getBootProperties(asyncResp);
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -08001669 getPCIeDeviceList(asyncResp);
Yong Li51709ff2019-09-30 14:13:04 +08001670 getHostWatchdogTimer(asyncResp);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001671 }
1672
Ed Tanous1abe55e2018-09-05 08:30:59 -07001673 void doPatch(crow::Response &res, const crow::Request &req,
1674 const std::vector<std::string> &params) override
1675 {
Santosh Puranikcde19e52019-02-20 00:10:56 +05301676 std::optional<std::string> indicatorLed;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301677 std::optional<nlohmann::json> bootProps;
Yong Lic45f0082019-10-10 14:19:01 +08001678 std::optional<nlohmann::json> wdtTimerProps;
Santosh Puranik41352c22019-07-03 05:35:49 -05001679 auto asyncResp = std::make_shared<AsyncResp>(res);
1680
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001681 if (!json_util::readJson(req, res, "IndicatorLED", indicatorLed, "Boot",
Yong Lic45f0082019-10-10 14:19:01 +08001682 bootProps, "WatchdogTimer", wdtTimerProps))
Ed Tanous66173382018-08-15 18:20:59 -07001683 {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001684 return;
1685 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301686
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001687 res.result(boost::beast::http::status::no_content);
Yong Lic45f0082019-10-10 14:19:01 +08001688
1689 if (wdtTimerProps)
1690 {
1691 std::optional<bool> wdtEnable;
1692 std::optional<std::string> wdtTimeOutAction;
1693
1694 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
1695 "FunctionEnabled", wdtEnable,
1696 "TimeoutAction", wdtTimeOutAction))
1697 {
1698 return;
1699 }
1700 setWDTProperties(asyncResp, std::move(wdtEnable),
1701 std::move(wdtTimeOutAction));
1702 }
1703
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301704 if (bootProps)
1705 {
1706 std::optional<std::string> bootSource;
1707 std::optional<std::string> bootEnable;
1708
1709 if (!json_util::readJson(*bootProps, asyncResp->res,
1710 "BootSourceOverrideTarget", bootSource,
1711 "BootSourceOverrideEnabled", bootEnable))
1712 {
1713 return;
1714 }
1715 setBootProperties(asyncResp, std::move(bootSource),
1716 std::move(bootEnable));
1717 }
Johnathan Mantey265c1602019-08-08 11:02:51 -07001718
Ed Tanous9712f8a2018-09-21 13:38:49 -07001719 if (indicatorLed)
1720 {
1721 std::string dbusLedState;
Jennifer Leed573bb22019-04-10 13:49:51 -07001722 if (*indicatorLed == "Lit")
Ed Tanous66173382018-08-15 18:20:59 -07001723 {
Jennifer Leed573bb22019-04-10 13:49:51 -07001724 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.On";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001725 }
Gunnar Mills5c6221a2019-02-22 11:24:29 -06001726 else if (*indicatorLed == "Blinking")
Ed Tanous9712f8a2018-09-21 13:38:49 -07001727 {
Gunnar Mills5c6221a2019-02-22 11:24:29 -06001728 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.Blink";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001729 }
1730 else if (*indicatorLed == "Off")
1731 {
1732 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.Off";
Ed Tanous66173382018-08-15 18:20:59 -07001733 }
1734 else
1735 {
Jason M. Billsa08b46c2018-11-06 15:01:08 -08001736 messages::propertyValueNotInList(res, *indicatorLed,
1737 "IndicatorLED");
Ed Tanous66173382018-08-15 18:20:59 -07001738 return;
1739 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001740
Ed Tanous9712f8a2018-09-21 13:38:49 -07001741 // Update led group
1742 BMCWEB_LOG_DEBUG << "Update led group.";
1743 crow::connections::systemBus->async_method_call(
Santosh Puranikcde19e52019-02-20 00:10:56 +05301744 [asyncResp](const boost::system::error_code ec) {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001745 if (ec)
1746 {
1747 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -07001748 messages::internalError(asyncResp->res);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001749 return;
1750 }
1751 BMCWEB_LOG_DEBUG << "Led group update done.";
1752 },
1753 "xyz.openbmc_project.LED.GroupManager",
1754 "/xyz/openbmc_project/led/groups/enclosure_identify",
1755 "org.freedesktop.DBus.Properties", "Set",
1756 "xyz.openbmc_project.Led.Group", "Asserted",
Ed Tanousabf2add2019-01-22 16:40:12 -08001757 std::variant<bool>(
Johnathan Mantey265c1602019-08-08 11:02:51 -07001758 (dbusLedState !=
1759 "xyz.openbmc_project.Led.Physical.Action.Off")));
1760
Ed Tanous9712f8a2018-09-21 13:38:49 -07001761 // Update identify led status
1762 BMCWEB_LOG_DEBUG << "Update led SoftwareInventoryCollection.";
1763 crow::connections::systemBus->async_method_call(
Johnathan Mantey265c1602019-08-08 11:02:51 -07001764 [asyncResp](const boost::system::error_code ec) {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001765 if (ec)
1766 {
1767 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -07001768 messages::internalError(asyncResp->res);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001769 return;
1770 }
1771 BMCWEB_LOG_DEBUG << "Led state update done.";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001772 },
1773 "xyz.openbmc_project.LED.Controller.identify",
1774 "/xyz/openbmc_project/led/physical/identify",
1775 "org.freedesktop.DBus.Properties", "Set",
1776 "xyz.openbmc_project.Led.Physical", "State",
Ed Tanousabf2add2019-01-22 16:40:12 -08001777 std::variant<std::string>(dbusLedState));
Ed Tanous1abe55e2018-09-05 08:30:59 -07001778 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001779 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001780};
Ed Tanous1abe55e2018-09-05 08:30:59 -07001781} // namespace redfish