blob: 2f2c97f8460fa1ca834ce559b5c41b5a858a30e7 [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 }
48 BMCWEB_LOG_DEBUG << "Dimm Functional:" << *isDimmFunctional;
49
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 }
83 BMCWEB_LOG_DEBUG << "Cpu Present:" << *isCpuPresent;
84
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 }
113 BMCWEB_LOG_DEBUG << "Cpu Functional:" << *isCpuFunctional;
114
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 */
Ed Tanous029573d2019-02-01 10:57:49 -0800139void getComputerSystem(std::shared_ptr<AsyncResp> aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700140{
Ed Tanous6c34de42018-08-29 13:37:36 -0700141 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500142
Ed Tanous6c34de42018-08-29 13:37:36 -0700143 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800144 [aResp](
Ed Tanous6c34de42018-08-29 13:37:36 -0700145 const boost::system::error_code ec,
146 const std::vector<std::pair<
147 std::string,
148 std::vector<std::pair<std::string, std::vector<std::string>>>>>
149 &subtree) {
150 if (ec)
151 {
152 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700153 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700154 return;
155 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700156 // Iterate over all retrieved ObjectPaths.
157 for (const std::pair<std::string,
158 std::vector<std::pair<
159 std::string, std::vector<std::string>>>>
160 &object : subtree)
161 {
162 const std::string &path = object.first;
163 BMCWEB_LOG_DEBUG << "Got path: " << path;
164 const std::vector<
165 std::pair<std::string, std::vector<std::string>>>
166 &connectionNames = object.second;
167 if (connectionNames.size() < 1)
168 {
169 continue;
170 }
Ed Tanous029573d2019-02-01 10:57:49 -0800171
172 // This is not system, so check if it's cpu, dimm, UUID or
173 // BiosVer
174 for (const auto &connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700175 {
Ed Tanous029573d2019-02-01 10:57:49 -0800176 for (const auto &interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700177 {
Ed Tanous029573d2019-02-01 10:57:49 -0800178 if (interfaceName ==
179 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700180 {
Ed Tanous029573d2019-02-01 10:57:49 -0800181 BMCWEB_LOG_DEBUG
182 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500183
Ed Tanous029573d2019-02-01 10:57:49 -0800184 crow::connections::systemBus->async_method_call(
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500185 [aResp, service{connection.first},
186 path(std::move(path))](
187 const boost::system::error_code ec,
188 const std::vector<
189 std::pair<std::string, VariantType>>
190 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800191 if (ec)
192 {
193 BMCWEB_LOG_ERROR
194 << "DBUS response error " << ec;
195 messages::internalError(aResp->res);
196 return;
197 }
198 BMCWEB_LOG_DEBUG << "Got "
199 << properties.size()
200 << "Dimm properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500201
202 if (properties.size() > 0)
Ed Tanous029573d2019-02-01 10:57:49 -0800203 {
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500204 for (const std::pair<std::string,
205 VariantType>
206 &property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700207 {
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500208 if (property.first ==
209 "MemorySizeInKb")
Ed Tanous6c34de42018-08-29 13:37:36 -0700210 {
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500211 const uint64_t *value =
212 sdbusplus::message::
213 variant_ns::get_if<
214 uint64_t>(
215 &property.second);
216 if (value != nullptr)
217 {
218 aResp->res.jsonValue
219 ["TotalSystemMemoryGi"
220 "B"] +=
221 *value / (1024 * 1024);
222 aResp->res.jsonValue
223 ["MemorySummary"]
224 ["Status"]["State"] =
225 "Enabled";
226 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700227 }
228 }
Ed Tanous029573d2019-02-01 10:57:49 -0800229 }
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500230 else
231 {
232 auto getDimmProperties =
233 [aResp](
234 const boost::system::error_code
235 ec,
236 const std::variant<bool>
237 &dimmState) {
238 if (ec)
239 {
240 BMCWEB_LOG_ERROR
241 << "DBUS response "
242 "error "
243 << ec;
244 return;
245 }
246 updateDimmProperties(aResp,
247 dimmState);
248 };
249 crow::connections::systemBus
250 ->async_method_call(
251 std::move(getDimmProperties),
252 service, path,
253 "org.freedesktop.DBus."
254 "Properties",
255 "Get",
256 "xyz.openbmc_project.State."
257 "Decorator.OperationalStatus",
258 "Functional");
259 }
Ed Tanous029573d2019-02-01 10:57:49 -0800260 },
261 connection.first, path,
262 "org.freedesktop.DBus.Properties", "GetAll",
263 "xyz.openbmc_project.Inventory.Item.Dimm");
264 }
265 else if (interfaceName ==
266 "xyz.openbmc_project.Inventory.Item.Cpu")
267 {
268 BMCWEB_LOG_DEBUG
269 << "Found Cpu, now get its properties.";
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500270
Ed Tanous029573d2019-02-01 10:57:49 -0800271 crow::connections::systemBus->async_method_call(
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500272 [aResp, service{connection.first},
273 path(std::move(path))](
274 const boost::system::error_code ec,
275 const std::vector<
276 std::pair<std::string, VariantType>>
277 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800278 if (ec)
279 {
280 BMCWEB_LOG_ERROR
281 << "DBUS response error " << ec;
282 messages::internalError(aResp->res);
283 return;
284 }
285 BMCWEB_LOG_DEBUG << "Got "
286 << properties.size()
287 << "Cpu properties.";
Ed Tanous04a258f2018-10-15 08:00:41 -0700288
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500289 if (properties.size() > 0)
290 {
291 for (const auto &property : properties)
292 {
293 if (property.first ==
294 "ProcessorFamily")
295 {
296 const std::string *value =
297 sdbusplus::message::
298 variant_ns::get_if<
299 std::string>(
300 &property.second);
301 if (value != nullptr)
302 {
303 nlohmann::json
304 &procSummary =
305 aResp->res.jsonValue
306 ["ProcessorSumm"
307 "ary"];
308 nlohmann::json &procCount =
309 procSummary["Count"];
310 procCount =
311 procCount.get<int>() +
312 1;
313 procSummary["Status"]
314 ["State"] =
315 "Enabled";
316 procSummary["Model"] =
317 *value;
318 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700319 }
320 }
Ed Tanous029573d2019-02-01 10:57:49 -0800321 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500322 else
323 {
324 auto getCpuPresenceState =
325 [aResp](
326 const boost::system::error_code
327 ec,
328 const std::variant<bool>
329 &cpuPresenceCheck) {
330 if (ec)
331 {
332 BMCWEB_LOG_ERROR
333 << "DBUS response "
334 "error "
335 << ec;
336 return;
337 }
338 modifyCpuPresenceState(
339 aResp, cpuPresenceCheck);
340 };
341
342 auto getCpuFunctionalState =
343 [aResp](
344 const boost::system::error_code
345 ec,
346 const std::variant<bool>
347 &cpuFunctionalCheck) {
348 if (ec)
349 {
350 BMCWEB_LOG_ERROR
351 << "DBUS response "
352 "error "
353 << ec;
354 return;
355 }
356 modifyCpuFunctionalState(
357 aResp, cpuFunctionalCheck);
358 };
359 // Get the Presence of CPU
360 crow::connections::systemBus
361 ->async_method_call(
362 std::move(getCpuPresenceState),
363 service, path,
364 "org.freedesktop.DBus."
365 "Properties",
366 "Get",
367 "xyz.openbmc_project.Inventory."
368 "Item",
369 "Present");
370
371 // Get the Functional State
372 crow::connections::systemBus
373 ->async_method_call(
374 std::move(
375 getCpuFunctionalState),
376 service, path,
377 "org.freedesktop.DBus."
378 "Properties",
379 "Get",
380 "xyz.openbmc_project.State."
381 "Decorator."
382 "OperationalStatus",
383 "Functional");
384
385 // Get the MODEL from
386 // xyz.openbmc_project.Inventory.Decorator.Asset
387 // support it later as Model is Empty
388 // currently.
389 }
Ed Tanous029573d2019-02-01 10:57:49 -0800390 },
391 connection.first, path,
392 "org.freedesktop.DBus.Properties", "GetAll",
393 "xyz.openbmc_project.Inventory.Item.Cpu");
394 }
395 else if (interfaceName ==
396 "xyz.openbmc_project.Common.UUID")
397 {
398 BMCWEB_LOG_DEBUG
399 << "Found UUID, now get its properties.";
400 crow::connections::systemBus->async_method_call(
401 [aResp](const boost::system::error_code ec,
Ed Tanous6c34de42018-08-29 13:37:36 -0700402 const std::vector<
403 std::pair<std::string, VariantType>>
404 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800405 if (ec)
406 {
407 BMCWEB_LOG_DEBUG
408 << "DBUS response error " << ec;
409 messages::internalError(aResp->res);
410 return;
411 }
412 BMCWEB_LOG_DEBUG << "Got "
413 << properties.size()
414 << "UUID properties.";
415 for (const std::pair<std::string,
416 VariantType>
417 &property : properties)
418 {
Ed Tanous029573d2019-02-01 10:57:49 -0800419 if (property.first == "UUID")
420 {
421 const std::string *value =
422 sdbusplus::message::variant_ns::
423 get_if<std::string>(
424 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700425
Ed Tanous029573d2019-02-01 10:57:49 -0800426 if (value != nullptr)
427 {
428 std::string valueStr = *value;
429 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700430 {
Ed Tanous029573d2019-02-01 10:57:49 -0800431 valueStr.insert(8, 1, '-');
432 valueStr.insert(13, 1, '-');
433 valueStr.insert(18, 1, '-');
434 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700435 }
Ed Tanous029573d2019-02-01 10:57:49 -0800436 BMCWEB_LOG_DEBUG << "UUID = "
437 << valueStr;
438 aResp->res.jsonValue["UUID"] =
439 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700440 }
441 }
Ed Tanous029573d2019-02-01 10:57:49 -0800442 }
443 },
444 connection.first, path,
445 "org.freedesktop.DBus.Properties", "GetAll",
446 "xyz.openbmc_project.Common.UUID");
447 }
448 else if (interfaceName ==
449 "xyz.openbmc_project.Inventory.Item.System")
450 {
451 crow::connections::systemBus->async_method_call(
452 [aResp](const boost::system::error_code ec,
453 const std::vector<
454 std::pair<std::string, VariantType>>
455 &propertiesList) {
456 if (ec)
457 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700458 // doesn't have to include this
459 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800460 return;
461 }
462 BMCWEB_LOG_DEBUG << "Got "
463 << propertiesList.size()
464 << "properties for system";
465 for (const std::pair<std::string,
466 VariantType>
467 &property : propertiesList)
468 {
beccabroekfc5afcf2019-03-05 14:35:15 -0600469 const std::string &propertyName =
470 property.first;
471 if ((propertyName == "PartNumber") ||
472 (propertyName == "SerialNumber") ||
473 (propertyName == "Manufacturer") ||
474 (propertyName == "Model"))
Ed Tanous029573d2019-02-01 10:57:49 -0800475 {
beccabroekfc5afcf2019-03-05 14:35:15 -0600476 const std::string *value =
477 std::get_if<std::string>(
478 &property.second);
479 if (value != nullptr)
480 {
481 aResp->res
482 .jsonValue[propertyName] =
483 *value;
484 }
Ed Tanous029573d2019-02-01 10:57:49 -0800485 }
486 }
487 aResp->res.jsonValue["Name"] = "system";
488 aResp->res.jsonValue["Id"] =
489 aResp->res.jsonValue["SerialNumber"];
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600490 // Grab the bios version
491 fw_util::getActiveFwVersion(
492 aResp, fw_util::biosPurpose,
493 "BiosVersion");
Ed Tanous029573d2019-02-01 10:57:49 -0800494 },
495 connection.first, path,
496 "org.freedesktop.DBus.Properties", "GetAll",
497 "xyz.openbmc_project.Inventory.Decorator."
498 "Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700499
500 crow::connections::systemBus->async_method_call(
501 [aResp](
502 const boost::system::error_code ec,
503 const std::variant<std::string> &property) {
504 if (ec)
505 {
506 // doesn't have to include this
507 // interface
508 return;
509 }
510
511 const std::string *value =
512 std::get_if<std::string>(&property);
513 if (value != nullptr)
514 {
515 aResp->res.jsonValue["AssetTag"] =
516 *value;
517 }
518 },
519 connection.first, path,
520 "org.freedesktop.DBus.Properties", "Get",
521 "xyz.openbmc_project.Inventory.Decorator."
522 "AssetTag",
523 "AssetTag");
Ed Tanous6c34de42018-08-29 13:37:36 -0700524 }
525 }
526 }
527 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700528 },
529 "xyz.openbmc_project.ObjectMapper",
530 "/xyz/openbmc_project/object_mapper",
531 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700532 "/xyz/openbmc_project/inventory", int32_t(0),
533 std::array<const char *, 5>{
534 "xyz.openbmc_project.Inventory.Decorator.Asset",
535 "xyz.openbmc_project.Inventory.Item.Cpu",
536 "xyz.openbmc_project.Inventory.Item.Dimm",
537 "xyz.openbmc_project.Inventory.Item.System",
538 "xyz.openbmc_project.Common.UUID",
539 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700540}
541
542/**
543 * @brief Retrieves identify led group properties over dbus
544 *
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530545 * @param[in] aResp Shared pointer for generating response message.
Ed Tanous6c34de42018-08-29 13:37:36 -0700546 * @param[in] callback Callback for process retrieved data.
547 *
548 * @return None.
549 */
550template <typename CallbackFunc>
551void getLedGroupIdentify(std::shared_ptr<AsyncResp> aResp,
552 CallbackFunc &&callback)
553{
554 BMCWEB_LOG_DEBUG << "Get led groups";
555 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800556 [aResp,
Ed Tanous66173382018-08-15 18:20:59 -0700557 callback{std::move(callback)}](const boost::system::error_code &ec,
558 const ManagedObjectsType &resp) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700559 if (ec)
560 {
561 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700562 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700563 return;
564 }
565 BMCWEB_LOG_DEBUG << "Got " << resp.size() << "led group objects.";
566 for (const auto &objPath : resp)
567 {
568 const std::string &path = objPath.first;
569 if (path.rfind("enclosure_identify") != std::string::npos)
570 {
571 for (const auto &interface : objPath.second)
572 {
573 if (interface.first == "xyz.openbmc_project.Led.Group")
574 {
575 for (const auto &property : interface.second)
576 {
577 if (property.first == "Asserted")
578 {
579 const bool *asserted =
Ed Tanousabf2add2019-01-22 16:40:12 -0800580 std::get_if<bool>(&property.second);
Ed Tanous6c34de42018-08-29 13:37:36 -0700581 if (nullptr != asserted)
582 {
583 callback(*asserted, aResp);
584 }
585 else
586 {
587 callback(false, aResp);
588 }
589 }
590 }
591 }
592 }
593 }
594 }
595 },
596 "xyz.openbmc_project.LED.GroupManager",
597 "/xyz/openbmc_project/led/groups", "org.freedesktop.DBus.ObjectManager",
598 "GetManagedObjects");
599}
600
601template <typename CallbackFunc>
602void getLedIdentify(std::shared_ptr<AsyncResp> aResp, CallbackFunc &&callback)
603{
604 BMCWEB_LOG_DEBUG << "Get identify led properties";
605 crow::connections::systemBus->async_method_call(
Ed Tanous66173382018-08-15 18:20:59 -0700606 [aResp,
607 callback{std::move(callback)}](const boost::system::error_code ec,
608 const PropertiesType &properties) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700609 if (ec)
610 {
611 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700612 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700613 return;
614 }
615 BMCWEB_LOG_DEBUG << "Got " << properties.size()
616 << "led properties.";
617 std::string output;
618 for (const auto &property : properties)
619 {
620 if (property.first == "State")
621 {
622 const std::string *s =
Ed Tanousabf2add2019-01-22 16:40:12 -0800623 std::get_if<std::string>(&property.second);
Ed Tanous6c34de42018-08-29 13:37:36 -0700624 if (nullptr != s)
625 {
626 BMCWEB_LOG_DEBUG << "Identify Led State: " << *s;
627 const auto pos = s->rfind('.');
628 if (pos != std::string::npos)
629 {
630 auto led = s->substr(pos + 1);
631 for (const std::pair<const char *, const char *>
632 &p :
633 std::array<
634 std::pair<const char *, const char *>, 3>{
635 {{"On", "Lit"},
636 {"Blink", "Blinking"},
637 {"Off", "Off"}}})
638 {
639 if (led == p.first)
640 {
641 output = p.second;
642 }
643 }
644 }
645 }
646 }
647 }
648 callback(output, aResp);
649 },
650 "xyz.openbmc_project.LED.Controller.identify",
651 "/xyz/openbmc_project/led/physical/identify",
652 "org.freedesktop.DBus.Properties", "GetAll",
653 "xyz.openbmc_project.Led.Physical");
654}
Ed Tanous6c34de42018-08-29 13:37:36 -0700655/**
656 * @brief Retrieves host state properties over dbus
657 *
658 * @param[in] aResp Shared pointer for completing asynchronous calls.
659 *
660 * @return None.
661 */
662void getHostState(std::shared_ptr<AsyncResp> aResp)
663{
664 BMCWEB_LOG_DEBUG << "Get host information.";
665 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800666 [aResp](const boost::system::error_code ec,
667 const std::variant<std::string> &hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700668 if (ec)
669 {
670 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700671 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700672 return;
673 }
Ed Tanous66173382018-08-15 18:20:59 -0700674
Ed Tanousabf2add2019-01-22 16:40:12 -0800675 const std::string *s = std::get_if<std::string>(&hostState);
Ed Tanous66173382018-08-15 18:20:59 -0700676 BMCWEB_LOG_DEBUG << "Host state: " << *s;
677 if (s != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700678 {
Ed Tanous66173382018-08-15 18:20:59 -0700679 // Verify Host State
Andrew Geissler94732662019-01-08 19:32:16 -0800680 if (*s == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700681 {
Ed Tanous66173382018-08-15 18:20:59 -0700682 aResp->res.jsonValue["PowerState"] = "On";
683 aResp->res.jsonValue["Status"]["State"] = "Enabled";
684 }
685 else
686 {
687 aResp->res.jsonValue["PowerState"] = "Off";
688 aResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700689 }
690 }
691 },
692 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Ed Tanous66173382018-08-15 18:20:59 -0700693 "org.freedesktop.DBus.Properties", "Get",
694 "xyz.openbmc_project.State.Host", "CurrentHostState");
Ed Tanous6c34de42018-08-29 13:37:36 -0700695}
696
697/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530698 * @brief Traslates boot source DBUS property value to redfish.
699 *
700 * @param[in] dbusSource The boot source in DBUS speak.
701 *
702 * @return Returns as a string, the boot source in Redfish terms. If translation
703 * cannot be done, returns an empty string.
704 */
705static std::string dbusToRfBootSource(const std::string &dbusSource)
706{
707 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
708 {
709 return "None";
710 }
711 else if (dbusSource ==
712 "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
713 {
714 return "Hdd";
715 }
716 else if (dbusSource ==
Santosh Puranika71dc0b2019-05-23 20:10:49 +0530717 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530718 {
719 return "Cd";
720 }
721 else if (dbusSource ==
722 "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
723 {
724 return "Pxe";
725 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700726 else if (dbusSource ==
727 "xyz.openbmc_project.Control.Boot.Source.Sources.Removable")
728 {
729 return "Usb";
730 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530731 else
732 {
733 return "";
734 }
735}
736
737/**
738 * @brief Traslates boot mode DBUS property value to redfish.
739 *
740 * @param[in] dbusMode The boot mode in DBUS speak.
741 *
742 * @return Returns as a string, the boot mode in Redfish terms. If translation
743 * cannot be done, returns an empty string.
744 */
745static std::string dbusToRfBootMode(const std::string &dbusMode)
746{
747 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
748 {
749 return "None";
750 }
751 else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
752 {
753 return "Diags";
754 }
755 else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
756 {
757 return "BiosSetup";
758 }
759 else
760 {
761 return "";
762 }
763}
764
765/**
766 * @brief Traslates boot source from Redfish to DBUS property value.
767 *
768 * @param[in] rfSource The boot source in Redfish.
769 *
770 * @return Returns as a string, the boot source as expected by DBUS.
771 * If translation cannot be done, returns an empty string.
772 */
773static std::string rfToDbusBootSource(const std::string &rfSource)
774{
775 if (rfSource == "None")
776 {
777 return "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
778 }
779 else if (rfSource == "Hdd")
780 {
781 return "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
782 }
783 else if (rfSource == "Cd")
784 {
Santosh Puranika71dc0b2019-05-23 20:10:49 +0530785 return "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530786 }
787 else if (rfSource == "Pxe")
788 {
789 return "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
790 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700791 else if (rfSource == "Usb")
792 {
793 return "xyz.openbmc_project.Control.Boot.Source.Sources.Removable";
794 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530795 else
796 {
797 return "";
798 }
799}
800
801/**
802 * @brief Traslates boot mode from Redfish to DBUS property value.
803 *
804 * @param[in] rfMode The boot mode in Redfish.
805 *
806 * @return Returns as a string, the boot mode as expected by DBUS.
807 * If translation cannot be done, returns an empty string.
808 */
809static std::string rfToDbusBootMode(const std::string &rfMode)
810{
811 if (rfMode == "None")
812 {
813 return "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
814 }
815 else if (rfMode == "Diags")
816 {
817 return "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
818 }
819 else if (rfMode == "BiosSetup")
820 {
821 return "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
822 }
823 else
824 {
825 return "";
826 }
827}
828
829/**
830 * @brief Retrieves boot mode over DBUS and fills out the response
831 *
832 * @param[in] aResp Shared pointer for generating response message.
833 * @param[in] bootDbusObj The dbus object to query for boot properties.
834 *
835 * @return None.
836 */
837static void getBootMode(std::shared_ptr<AsyncResp> aResp,
838 std::string bootDbusObj)
839{
840 crow::connections::systemBus->async_method_call(
841 [aResp](const boost::system::error_code ec,
842 const std::variant<std::string> &bootMode) {
843 if (ec)
844 {
845 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
846 messages::internalError(aResp->res);
847 return;
848 }
849
850 const std::string *bootModeStr =
851 std::get_if<std::string>(&bootMode);
852
853 if (!bootModeStr)
854 {
855 messages::internalError(aResp->res);
856 return;
857 }
858
859 BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
860
861 // TODO (Santosh): Do we need to support override mode?
862 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = "Legacy";
863 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
864 "AllowableValues"] = {
865 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup"};
866
867 if (*bootModeStr !=
868 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
869 {
870 auto rfMode = dbusToRfBootMode(*bootModeStr);
871 if (!rfMode.empty())
872 {
873 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
874 rfMode;
875 }
876 }
877
878 // If the BootSourceOverrideTarget is still "None" at the end,
879 // reset the BootSourceOverrideEnabled to indicate that
880 // overrides are disabled
881 if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] ==
882 "None")
883 {
884 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
885 "Disabled";
886 }
887 },
888 "xyz.openbmc_project.Settings", bootDbusObj,
889 "org.freedesktop.DBus.Properties", "Get",
890 "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
891}
892
893/**
894 * @brief Retrieves boot source over DBUS
895 *
896 * @param[in] aResp Shared pointer for generating response message.
897 * @param[in] oneTimeEnable Boolean to indicate boot properties are one-time.
898 *
899 * @return None.
900 */
901static void getBootSource(std::shared_ptr<AsyncResp> aResp, bool oneTimeEnabled)
902{
903 std::string bootDbusObj =
904 oneTimeEnabled ? "/xyz/openbmc_project/control/host0/boot/one_time"
905 : "/xyz/openbmc_project/control/host0/boot";
906
907 BMCWEB_LOG_DEBUG << "Is one time: " << oneTimeEnabled;
908 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
909 (oneTimeEnabled) ? "Once" : "Continuous";
910
911 crow::connections::systemBus->async_method_call(
912 [aResp, bootDbusObj](const boost::system::error_code ec,
913 const std::variant<std::string> &bootSource) {
914 if (ec)
915 {
916 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
917 messages::internalError(aResp->res);
918 return;
919 }
920
921 const std::string *bootSourceStr =
922 std::get_if<std::string>(&bootSource);
923
924 if (!bootSourceStr)
925 {
926 messages::internalError(aResp->res);
927 return;
928 }
929 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
930
931 auto rfSource = dbusToRfBootSource(*bootSourceStr);
932 if (!rfSource.empty())
933 {
934 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
935 rfSource;
936 }
937 },
938 "xyz.openbmc_project.Settings", bootDbusObj,
939 "org.freedesktop.DBus.Properties", "Get",
940 "xyz.openbmc_project.Control.Boot.Source", "BootSource");
941 getBootMode(std::move(aResp), std::move(bootDbusObj));
942}
943
944/**
945 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
946 * get boot source and boot mode.
947 *
948 * @param[in] aResp Shared pointer for generating response message.
949 *
950 * @return None.
951 */
952static void getBootProperties(std::shared_ptr<AsyncResp> aResp)
953{
954 BMCWEB_LOG_DEBUG << "Get boot information.";
955
956 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800957 [aResp](const boost::system::error_code ec,
958 const sdbusplus::message::variant<bool> &oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530959 if (ec)
960 {
961 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
James Feist2a833c72019-07-19 10:17:13 -0700962 // not an error, don't have to have the interface
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530963 return;
964 }
965
966 const bool *oneTimePtr = std::get_if<bool>(&oneTime);
967
968 if (!oneTimePtr)
969 {
970 messages::internalError(aResp->res);
971 return;
972 }
973 getBootSource(aResp, *oneTimePtr);
974 },
975 "xyz.openbmc_project.Settings",
976 "/xyz/openbmc_project/control/host0/boot/one_time",
977 "org.freedesktop.DBus.Properties", "Get",
978 "xyz.openbmc_project.Object.Enable", "Enabled");
979}
980
981/**
982 * @brief Sets boot properties into DBUS object(s).
983 *
984 * @param[in] aResp Shared pointer for generating response message.
985 * @param[in] oneTimeEnabled Is "one-time" setting already enabled.
986 * @param[in] bootSource The boot source to set.
987 * @param[in] bootEnable The source override "enable" to set.
988 *
989 * @return None.
990 */
991static void setBootModeOrSource(std::shared_ptr<AsyncResp> aResp,
992 bool oneTimeEnabled,
993 std::optional<std::string> bootSource,
994 std::optional<std::string> bootEnable)
995{
996 if (bootEnable && (bootEnable != "Once") && (bootEnable != "Continuous") &&
997 (bootEnable != "Disabled"))
998 {
999 BMCWEB_LOG_DEBUG << "Unsupported value for BootSourceOverrideEnabled: "
1000 << *bootEnable;
1001 messages::propertyValueNotInList(aResp->res, *bootEnable,
1002 "BootSourceOverrideEnabled");
1003 return;
1004 }
1005
1006 bool oneTimeSetting = oneTimeEnabled;
1007 // Validate incoming parameters
1008 if (bootEnable)
1009 {
1010 if (*bootEnable == "Once")
1011 {
1012 oneTimeSetting = true;
1013 }
1014 else if (*bootEnable == "Continuous")
1015 {
1016 oneTimeSetting = false;
1017 }
1018 else if (*bootEnable == "Disabled")
1019 {
1020 oneTimeSetting = false;
1021 }
1022 else
1023 {
1024
1025 BMCWEB_LOG_DEBUG << "Unsupported value for "
1026 "BootSourceOverrideEnabled: "
1027 << *bootEnable;
1028 messages::propertyValueNotInList(aResp->res, *bootEnable,
1029 "BootSourceOverrideEnabled");
1030 return;
1031 }
1032 }
1033 std::string bootSourceStr;
1034 std::string bootModeStr;
1035 if (bootSource)
1036 {
1037 bootSourceStr = rfToDbusBootSource(*bootSource);
1038 bootModeStr = rfToDbusBootMode(*bootSource);
1039
1040 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1041 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
1042
1043 if (bootSourceStr.empty() && bootModeStr.empty())
1044 {
1045 BMCWEB_LOG_DEBUG << "Invalid property value for "
1046 "BootSourceOverrideTarget: "
1047 << *bootSource;
1048 messages::propertyValueNotInList(aResp->res, *bootSource,
1049 "BootSourceTargetOverride");
1050 return;
1051 }
1052 }
1053 const char *bootObj =
1054 oneTimeSetting ? "/xyz/openbmc_project/control/host0/boot/one_time"
1055 : "/xyz/openbmc_project/control/host0/boot";
1056 // Figure out what properties to set
1057 if (bootEnable && (*bootEnable == "Disabled"))
1058 {
1059 BMCWEB_LOG_DEBUG << "Boot source override will be disabled";
1060 // Request to only turn OFF/ON enabled, if turning enabled OFF, need
1061 // to reset the source and mode too. If turning it ON, we only need
1062 // to set the enabled property
1063 bootSourceStr =
1064 "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
1065 bootModeStr = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
1066 }
1067 else if (bootSource)
1068 {
1069 // Source target specified
1070 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1071 // Figure out which DBUS interface and property to use
1072 bootSourceStr = rfToDbusBootSource(*bootSource);
1073 bootModeStr = rfToDbusBootMode(*bootSource);
1074
1075 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1076 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
1077
1078 if (bootSourceStr.empty() && bootModeStr.empty())
1079 {
1080 BMCWEB_LOG_DEBUG << "Invalid property value for "
1081 "BootSourceOverrideTarget: "
1082 << *bootSource;
1083 messages::propertyValueNotInList(aResp->res, *bootSource,
1084 "BootSourceTargetOverride");
1085 return;
1086 }
1087
1088 if (!bootSourceStr.empty())
1089 {
1090 // If setting to anything other than default, also reset boot
1091 // mode property
1092 if (bootSourceStr !=
1093 "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
1094 {
1095 bootModeStr =
1096 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
1097 }
1098 }
1099 else // if (!bootModeStr.empty())
1100 {
1101 // If setting to anything other than default, also reset boot
1102 // source property
1103 if (bootModeStr !=
1104 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
1105 {
1106 bootSourceStr =
1107 "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
1108 }
1109 }
1110 }
1111 if (!bootSourceStr.empty())
1112 {
1113 crow::connections::systemBus->async_method_call(
1114 [aResp](const boost::system::error_code ec) {
1115 if (ec)
1116 {
1117 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1118 messages::internalError(aResp->res);
1119 return;
1120 }
1121 BMCWEB_LOG_DEBUG << "Boot source update done.";
1122 },
1123 "xyz.openbmc_project.Settings", bootObj,
1124 "org.freedesktop.DBus.Properties", "Set",
1125 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1126 std::variant<std::string>(bootSourceStr));
1127 }
1128 if (!bootModeStr.empty())
1129 {
1130 crow::connections::systemBus->async_method_call(
1131 [aResp](const boost::system::error_code ec) {
1132 if (ec)
1133 {
1134 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1135 messages::internalError(aResp->res);
1136 return;
1137 }
1138 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1139 },
1140 "xyz.openbmc_project.Settings", bootObj,
1141 "org.freedesktop.DBus.Properties", "Set",
1142 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1143 std::variant<std::string>(bootModeStr));
1144 }
1145 crow::connections::systemBus->async_method_call(
1146 [aResp{std::move(aResp)}](const boost::system::error_code ec) {
1147 if (ec)
1148 {
1149 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1150 messages::internalError(aResp->res);
1151 return;
1152 }
1153 BMCWEB_LOG_DEBUG << "Boot enable update done.";
1154 },
1155 "xyz.openbmc_project.Settings",
1156 "/xyz/openbmc_project/control/host0/boot/one_time",
1157 "org.freedesktop.DBus.Properties", "Set",
1158 "xyz.openbmc_project.Object.Enable", "Enabled",
1159 std::variant<bool>(oneTimeSetting));
1160}
1161
1162/**
1163 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
1164 * set boot source/boot mode properties.
1165 *
1166 * @param[in] aResp Shared pointer for generating response message.
1167 * @param[in] bootSource The boot source from incoming RF request.
1168 * @param[in] bootEnable The boot override enable from incoming RF request.
1169 *
1170 * @return None.
1171 */
1172static void setBootProperties(std::shared_ptr<AsyncResp> aResp,
1173 std::optional<std::string> bootSource,
1174 std::optional<std::string> bootEnable)
1175{
1176 BMCWEB_LOG_DEBUG << "Set boot information.";
1177
1178 crow::connections::systemBus->async_method_call(
1179 [aResp{std::move(aResp)}, bootSource{std::move(bootSource)},
1180 bootEnable{std::move(bootEnable)}](
1181 const boost::system::error_code ec,
1182 const sdbusplus::message::variant<bool> &oneTime) {
1183 if (ec)
1184 {
1185 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1186 messages::internalError(aResp->res);
1187 return;
1188 }
1189
1190 const bool *oneTimePtr = std::get_if<bool>(&oneTime);
1191
1192 if (!oneTimePtr)
1193 {
1194 messages::internalError(aResp->res);
1195 return;
1196 }
1197
1198 BMCWEB_LOG_DEBUG << "Got one time: " << *oneTimePtr;
1199
1200 setBootModeOrSource(aResp, *oneTimePtr, std::move(bootSource),
1201 std::move(bootEnable));
1202 },
1203 "xyz.openbmc_project.Settings",
1204 "/xyz/openbmc_project/control/host0/boot/one_time",
1205 "org.freedesktop.DBus.Properties", "Get",
1206 "xyz.openbmc_project.Object.Enable", "Enabled");
1207}
1208
1209/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001210 * SystemsCollection derived class for delivering ComputerSystems Collection
1211 * Schema
1212 */
Ed Tanous1abe55e2018-09-05 08:30:59 -07001213class SystemsCollection : public Node
1214{
1215 public:
1216 SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/")
1217 {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001218 entityPrivileges = {
1219 {boost::beast::http::verb::get, {{"Login"}}},
1220 {boost::beast::http::verb::head, {{"Login"}}},
1221 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1222 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1223 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1224 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1225 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001226
Ed Tanous1abe55e2018-09-05 08:30:59 -07001227 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -07001228 void doGet(crow::Response &res, const crow::Request &req,
1229 const std::vector<std::string> &params) override
1230 {
Ed Tanous0f74e642018-11-12 15:17:05 -08001231 res.jsonValue["@odata.type"] =
1232 "#ComputerSystemCollection.ComputerSystemCollection";
1233 res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
1234 res.jsonValue["@odata.context"] =
1235 "/redfish/v1/"
1236 "$metadata#ComputerSystemCollection.ComputerSystemCollection";
1237 res.jsonValue["Name"] = "Computer System Collection";
Ed Tanous029573d2019-02-01 10:57:49 -08001238 res.jsonValue["Members"] = {
1239 {{"@odata.id", "/redfish/v1/Systems/system"}}};
1240 res.jsonValue["Members@odata.count"] = 1;
1241 res.end();
Ed Tanous1abe55e2018-09-05 08:30:59 -07001242 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001243};
1244
1245/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07001246 * SystemActionsReset class supports handle POST method for Reset action.
1247 * The class retrieves and sends data directly to D-Bus.
1248 */
1249class SystemActionsReset : public Node
1250{
1251 public:
1252 SystemActionsReset(CrowApp &app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001253 Node(app, "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanouscc340dd2018-08-29 13:43:38 -07001254 {
1255 entityPrivileges = {
1256 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1257 }
1258
1259 private:
1260 /**
1261 * Function handles POST method request.
1262 * Analyzes POST body message before sends Reset request data to D-Bus.
1263 */
1264 void doPost(crow::Response &res, const crow::Request &req,
1265 const std::vector<std::string> &params) override
1266 {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001267 auto asyncResp = std::make_shared<AsyncResp>(res);
1268
1269 std::string resetType;
1270 if (!json_util::readJson(req, res, "ResetType", resetType))
Ed Tanouscc340dd2018-08-29 13:43:38 -07001271 {
1272 return;
1273 }
1274
Jason M. Billsd22c8392019-06-03 13:59:03 -07001275 // Get the command and host vs. chassis
Ed Tanous9712f8a2018-09-21 13:38:49 -07001276 std::string command;
Jason M. Billsd22c8392019-06-03 13:59:03 -07001277 bool hostCommand;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001278 if (resetType == "On")
1279 {
1280 command = "xyz.openbmc_project.State.Host.Transition.On";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001281 hostCommand = true;
1282 }
1283 else if (resetType == "ForceOff")
1284 {
1285 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
1286 hostCommand = false;
1287 }
1288 else if (resetType == "ForceOn")
1289 {
1290 command = "xyz.openbmc_project.State.Host.Transition.On";
1291 hostCommand = true;
1292 }
1293 else if (resetType == "ForceRestart")
1294 {
1295 command = "xyz.openbmc_project.State.Chassis.Transition.Reset";
1296 hostCommand = false;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001297 }
1298 else if (resetType == "GracefulShutdown")
1299 {
1300 command = "xyz.openbmc_project.State.Host.Transition.Off";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001301 hostCommand = true;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001302 }
1303 else if (resetType == "GracefulRestart")
1304 {
1305 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001306 hostCommand = true;
1307 }
1308 else if (resetType == "PowerCycle")
1309 {
1310 command = "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
1311 hostCommand = false;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001312 }
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001313 else if (resetType == "Nmi")
1314 {
1315 doNMI(asyncResp);
1316 return;
1317 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001318 else
1319 {
Jason M. Billsf12894f2018-10-09 12:45:45 -07001320 messages::actionParameterUnknown(res, "Reset", resetType);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001321 return;
1322 }
1323
Jason M. Billsd22c8392019-06-03 13:59:03 -07001324 if (hostCommand)
1325 {
1326 crow::connections::systemBus->async_method_call(
1327 [asyncResp, resetType](const boost::system::error_code ec) {
1328 if (ec)
1329 {
1330 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1331 if (ec.value() == boost::asio::error::invalid_argument)
1332 {
1333 messages::actionParameterNotSupported(
1334 asyncResp->res, resetType, "Reset");
1335 }
1336 else
1337 {
1338 messages::internalError(asyncResp->res);
1339 }
1340 return;
1341 }
1342 messages::success(asyncResp->res);
1343 },
1344 "xyz.openbmc_project.State.Host",
1345 "/xyz/openbmc_project/state/host0",
1346 "org.freedesktop.DBus.Properties", "Set",
1347 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
1348 std::variant<std::string>{command});
1349 }
1350 else
1351 {
1352 crow::connections::systemBus->async_method_call(
1353 [asyncResp, resetType](const boost::system::error_code ec) {
1354 if (ec)
1355 {
1356 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1357 if (ec.value() == boost::asio::error::invalid_argument)
1358 {
1359 messages::actionParameterNotSupported(
1360 asyncResp->res, resetType, "Reset");
1361 }
1362 else
1363 {
1364 messages::internalError(asyncResp->res);
1365 }
1366 return;
1367 }
1368 messages::success(asyncResp->res);
1369 },
1370 "xyz.openbmc_project.State.Chassis",
1371 "/xyz/openbmc_project/state/chassis0",
1372 "org.freedesktop.DBus.Properties", "Set",
1373 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
1374 std::variant<std::string>{command});
1375 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07001376 }
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001377 /**
1378 * Function transceives data with dbus directly.
1379 */
1380 void doNMI(const std::shared_ptr<AsyncResp> &asyncResp)
1381 {
1382 constexpr char const *serviceName =
1383 "xyz.openbmc_project.Control.Host.NMI";
1384 constexpr char const *objectPath =
1385 "/xyz/openbmc_project/control/host0/nmi";
1386 constexpr char const *interfaceName =
1387 "xyz.openbmc_project.Control.Host.NMI";
1388 constexpr char const *method = "NMI";
1389
1390 crow::connections::systemBus->async_method_call(
1391 [asyncResp](const boost::system::error_code ec) {
1392 if (ec)
1393 {
1394 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
1395 messages::internalError(asyncResp->res);
1396 return;
1397 }
1398 messages::success(asyncResp->res);
1399 },
1400 serviceName, objectPath, interfaceName, method);
1401 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07001402};
1403
1404/**
Ed Tanous66173382018-08-15 18:20:59 -07001405 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001406 */
Ed Tanous1abe55e2018-09-05 08:30:59 -07001407class Systems : public Node
1408{
1409 public:
1410 /*
1411 * Default Constructor
1412 */
Ed Tanous029573d2019-02-01 10:57:49 -08001413 Systems(CrowApp &app) : Node(app, "/redfish/v1/Systems/system/")
Ed Tanous1abe55e2018-09-05 08:30:59 -07001414 {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001415 entityPrivileges = {
1416 {boost::beast::http::verb::get, {{"Login"}}},
1417 {boost::beast::http::verb::head, {{"Login"}}},
1418 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1419 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1420 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1421 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001422 }
1423
Ed Tanous1abe55e2018-09-05 08:30:59 -07001424 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -07001425 /**
1426 * Functions triggers appropriate requests on DBus
1427 */
1428 void doGet(crow::Response &res, const crow::Request &req,
1429 const std::vector<std::string> &params) override
1430 {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301431 res.jsonValue["@odata.type"] = "#ComputerSystem.v1_6_0.ComputerSystem";
Ed Tanous0f74e642018-11-12 15:17:05 -08001432 res.jsonValue["@odata.context"] =
1433 "/redfish/v1/$metadata#ComputerSystem.ComputerSystem";
Ed Tanous029573d2019-02-01 10:57:49 -08001434 res.jsonValue["Name"] = "Computer System";
1435 res.jsonValue["Id"] = "system";
Ed Tanous0f74e642018-11-12 15:17:05 -08001436 res.jsonValue["SystemType"] = "Physical";
1437 res.jsonValue["Description"] = "Computer System";
Ed Tanous0f74e642018-11-12 15:17:05 -08001438 res.jsonValue["ProcessorSummary"]["Count"] = 0;
1439 res.jsonValue["ProcessorSummary"]["Status"]["State"] = "Disabled";
1440 res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] = int(0);
1441 res.jsonValue["MemorySummary"]["Status"]["State"] = "Disabled";
Ed Tanous029573d2019-02-01 10:57:49 -08001442 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07001443
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001444 res.jsonValue["Processors"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001445 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001446 res.jsonValue["Memory"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001447 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
1448
Ed Tanouscc340dd2018-08-29 13:43:38 -07001449 // TODO Need to support ForceRestart.
1450 res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
1451 {"target",
Ed Tanous029573d2019-02-01 10:57:49 -08001452 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
Ed Tanouscc340dd2018-08-29 13:43:38 -07001453 {"ResetType@Redfish.AllowableValues",
Jason M. Billsd22c8392019-06-03 13:59:03 -07001454 {"On", "ForceOff", "ForceOn", "ForceRestart", "GracefulRestart",
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001455 "GracefulShutdown", "PowerCycle", "Nmi"}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001456
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001457 res.jsonValue["LogServices"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001458 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001459
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001460 res.jsonValue["Links"]["ManagedBy"] = {
1461 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
1462
1463 res.jsonValue["Status"] = {
1464 {"Health", "OK"},
1465 {"State", "Enabled"},
1466 };
Ed Tanousa0803ef2018-08-29 13:29:23 -07001467 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001468
James Feistb49ac872019-05-21 15:12:01 -07001469 constexpr const std::array<const char *, 2> inventoryForSystems = {
1470 "xyz.openbmc_project.Inventory.Item.Dimm",
1471 "xyz.openbmc_project.Inventory.Item.Cpu"};
1472
1473 auto health = std::make_shared<HealthPopulate>(asyncResp);
1474 crow::connections::systemBus->async_method_call(
1475 [health](const boost::system::error_code ec,
1476 std::vector<std::string> &resp) {
1477 if (ec)
1478 {
1479 // no inventory
1480 return;
1481 }
1482
1483 health->inventory = std::move(resp);
1484 },
1485 "xyz.openbmc_project.ObjectMapper",
1486 "/xyz/openbmc_project/object_mapper",
1487 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
1488 int32_t(0), inventoryForSystems);
1489
1490 health->populate();
1491
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001492 getMainChassisId(asyncResp, [](const std::string &chassisId,
1493 std::shared_ptr<AsyncResp> aRsp) {
1494 aRsp->res.jsonValue["Links"]["Chassis"] = {
1495 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
1496 });
Ed Tanous6c34de42018-08-29 13:37:36 -07001497 getLedGroupIdentify(
Ed Tanousa0803ef2018-08-29 13:29:23 -07001498 asyncResp,
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001499 [](const bool &asserted, const std::shared_ptr<AsyncResp> aRsp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001500 if (asserted)
1501 {
1502 // If led group is asserted, then another call is needed to
1503 // get led status
Ed Tanous6c34de42018-08-29 13:37:36 -07001504 getLedIdentify(
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001505 aRsp, [](const std::string &ledStatus,
1506 const std::shared_ptr<AsyncResp> aRsp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001507 if (!ledStatus.empty())
1508 {
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001509 aRsp->res.jsonValue["IndicatorLED"] = ledStatus;
Ed Tanous1abe55e2018-09-05 08:30:59 -07001510 }
1511 });
1512 }
1513 else
1514 {
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001515 aRsp->res.jsonValue["IndicatorLED"] = "Off";
Ed Tanous1abe55e2018-09-05 08:30:59 -07001516 }
1517 });
Ed Tanous029573d2019-02-01 10:57:49 -08001518 getComputerSystem(asyncResp);
Ed Tanous6c34de42018-08-29 13:37:36 -07001519 getHostState(asyncResp);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301520 getBootProperties(asyncResp);
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -08001521 getPCIeDeviceList(asyncResp);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001522 }
1523
Ed Tanous1abe55e2018-09-05 08:30:59 -07001524 void doPatch(crow::Response &res, const crow::Request &req,
1525 const std::vector<std::string> &params) override
1526 {
Santosh Puranikcde19e52019-02-20 00:10:56 +05301527 std::optional<std::string> indicatorLed;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301528 std::optional<nlohmann::json> bootProps;
Santosh Puranik41352c22019-07-03 05:35:49 -05001529 auto asyncResp = std::make_shared<AsyncResp>(res);
1530
1531 if (!json_util::readJson(req, asyncResp->res, "IndicatorLED",
1532 indicatorLed, "Boot", bootProps))
Ed Tanous66173382018-08-15 18:20:59 -07001533 {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001534 return;
1535 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301536
Jennifer Leed573bb22019-04-10 13:49:51 -07001537 asyncResp->res.result(boost::beast::http::status::no_content);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301538
1539 if (bootProps)
1540 {
1541 std::optional<std::string> bootSource;
1542 std::optional<std::string> bootEnable;
1543
1544 if (!json_util::readJson(*bootProps, asyncResp->res,
1545 "BootSourceOverrideTarget", bootSource,
1546 "BootSourceOverrideEnabled", bootEnable))
1547 {
1548 return;
1549 }
1550 setBootProperties(asyncResp, std::move(bootSource),
1551 std::move(bootEnable));
1552 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001553 if (indicatorLed)
1554 {
1555 std::string dbusLedState;
Jennifer Leed573bb22019-04-10 13:49:51 -07001556 if (*indicatorLed == "Lit")
Ed Tanous66173382018-08-15 18:20:59 -07001557 {
Jennifer Leed573bb22019-04-10 13:49:51 -07001558 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.On";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001559 }
Gunnar Mills5c6221a2019-02-22 11:24:29 -06001560 else if (*indicatorLed == "Blinking")
Ed Tanous9712f8a2018-09-21 13:38:49 -07001561 {
Gunnar Mills5c6221a2019-02-22 11:24:29 -06001562 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.Blink";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001563 }
1564 else if (*indicatorLed == "Off")
1565 {
1566 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.Off";
Ed Tanous66173382018-08-15 18:20:59 -07001567 }
1568 else
1569 {
Jason M. Billsa08b46c2018-11-06 15:01:08 -08001570 messages::propertyValueNotInList(res, *indicatorLed,
1571 "IndicatorLED");
Ed Tanous66173382018-08-15 18:20:59 -07001572 return;
1573 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001574
Ed Tanous9712f8a2018-09-21 13:38:49 -07001575 // Update led group
1576 BMCWEB_LOG_DEBUG << "Update led group.";
1577 crow::connections::systemBus->async_method_call(
Santosh Puranikcde19e52019-02-20 00:10:56 +05301578 [asyncResp](const boost::system::error_code ec) {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001579 if (ec)
1580 {
1581 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -07001582 messages::internalError(asyncResp->res);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001583 return;
1584 }
1585 BMCWEB_LOG_DEBUG << "Led group update done.";
1586 },
1587 "xyz.openbmc_project.LED.GroupManager",
1588 "/xyz/openbmc_project/led/groups/enclosure_identify",
1589 "org.freedesktop.DBus.Properties", "Set",
1590 "xyz.openbmc_project.Led.Group", "Asserted",
Ed Tanousabf2add2019-01-22 16:40:12 -08001591 std::variant<bool>(
Ed Tanous9712f8a2018-09-21 13:38:49 -07001592 (dbusLedState ==
1593 "xyz.openbmc_project.Led.Physical.Action.Off"
1594 ? false
1595 : true)));
1596 // Update identify led status
1597 BMCWEB_LOG_DEBUG << "Update led SoftwareInventoryCollection.";
1598 crow::connections::systemBus->async_method_call(
1599 [asyncResp{std::move(asyncResp)},
1600 indicatorLed{std::move(*indicatorLed)}](
1601 const boost::system::error_code ec) {
1602 if (ec)
1603 {
1604 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -07001605 messages::internalError(asyncResp->res);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001606 return;
1607 }
1608 BMCWEB_LOG_DEBUG << "Led state update done.";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001609 },
1610 "xyz.openbmc_project.LED.Controller.identify",
1611 "/xyz/openbmc_project/led/physical/identify",
1612 "org.freedesktop.DBus.Properties", "Set",
1613 "xyz.openbmc_project.Led.Physical", "State",
Ed Tanousabf2add2019-01-22 16:40:12 -08001614 std::variant<std::string>(dbusLedState));
Ed Tanous1abe55e2018-09-05 08:30:59 -07001615 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001616 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001617};
Ed Tanous1abe55e2018-09-05 08:30:59 -07001618} // namespace redfish