blob: 5f9801bc6e7c66e7efa736d765c842fc3a9b0c47 [file] [log] [blame]
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
James Feistb49ac872019-05-21 15:12:01 -070018#include "health.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080019#include "led.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080020#include "pcie.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080021#include "redfish_util.hpp"
22
Ed Tanous9712f8a2018-09-21 13:38:49 -070023#include <boost/container/flat_map.hpp>
24#include <node.hpp>
Andrew Geisslercb7e1e72019-02-19 13:05:38 -060025#include <utils/fw_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020026#include <utils/json_utils.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050027
Ed Tanousabf2add2019-01-22 16:40:12 -080028#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020029
Ed Tanous1abe55e2018-09-05 08:30:59 -070030namespace redfish
31{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020032
Alpana Kumari9d3ae102019-04-12 06:49:32 -050033/**
34 * @brief Updates the Functional State of DIMMs
35 *
36 * @param[in] aResp Shared pointer for completing asynchronous calls
37 * @param[in] dimmState Dimm's Functional state, true/false
38 *
39 * @return None.
40 */
Ed Tanousb5a76932020-09-29 16:16:58 -070041inline void updateDimmProperties(const std::shared_ptr<AsyncResp>& aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +000042 const std::variant<bool>& dimmState)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050043{
Gunnar Mills1214b7e2020-06-04 10:11:30 -050044 const bool* isDimmFunctional = std::get_if<bool>(&dimmState);
Alpana Kumari9d3ae102019-04-12 06:49:32 -050045 if (isDimmFunctional == nullptr)
46 {
47 messages::internalError(aResp->res);
48 return;
49 }
Gunnar Mills698654b2019-10-16 13:17:37 -050050 BMCWEB_LOG_DEBUG << "Dimm Functional: " << *isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050051
Gunnar Mills4e0453b2020-07-08 14:00:30 -050052 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050053 // Update STATE only if previous State was DISABLED and current Dimm is
54 // ENABLED.
Gunnar Mills1214b7e2020-06-04 10:11:30 -050055 nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050056 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
57 if (prevMemSummary == "Disabled")
58 {
59 if (*isDimmFunctional == true)
60 {
61 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
62 "Enabled";
63 }
64 }
65}
66
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050067/*
68 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
69 *
70 * @param[in] aResp Shared pointer for completing asynchronous calls
71 * @param[in] cpuPresenceState CPU present or not
72 *
73 * @return None.
74 */
Ed Tanousb5a76932020-09-29 16:16:58 -070075inline void modifyCpuPresenceState(const std::shared_ptr<AsyncResp>& aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +000076 const std::variant<bool>& cpuPresenceState)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050077{
Gunnar Mills1214b7e2020-06-04 10:11:30 -050078 const bool* isCpuPresent = std::get_if<bool>(&cpuPresenceState);
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050079
80 if (isCpuPresent == nullptr)
81 {
82 messages::internalError(aResp->res);
83 return;
84 }
Gunnar Mills698654b2019-10-16 13:17:37 -050085 BMCWEB_LOG_DEBUG << "Cpu Present: " << *isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050086
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050087 if (*isCpuPresent == true)
88 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050089 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080090 aResp->res.jsonValue["ProcessorSummary"]["Count"];
91 auto procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050092 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080093 if (procCountPtr != nullptr)
94 {
95 // shouldn't be possible to be nullptr
96 *procCountPtr += 1;
97 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050098 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050099}
100
101/*
102 * @brief Update "ProcessorSummary" "Status" "State" based on
103 * CPU Functional State
104 *
105 * @param[in] aResp Shared pointer for completing asynchronous calls
106 * @param[in] cpuFunctionalState is CPU functional true/false
107 *
108 * @return None.
109 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000110inline void
Ed Tanousb5a76932020-09-29 16:16:58 -0700111 modifyCpuFunctionalState(const std::shared_ptr<AsyncResp>& aResp,
Ed Tanous23a21a12020-07-25 04:45:05 +0000112 const std::variant<bool>& cpuFunctionalState)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500113{
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500114 const bool* isCpuFunctional = std::get_if<bool>(&cpuFunctionalState);
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500115
116 if (isCpuFunctional == nullptr)
117 {
118 messages::internalError(aResp->res);
119 return;
120 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500121 BMCWEB_LOG_DEBUG << "Cpu Functional: " << *isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500122
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500123 nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500124 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
125
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500126 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500127 // Update STATE only if previous State was Non_Functional and current CPU is
128 // Functional.
129 if (prevProcState == "Disabled")
130 {
131 if (*isCpuFunctional == true)
132 {
133 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
134 "Enabled";
135 }
136 }
137}
138
139/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700140 * @brief Retrieves computer system properties over dbus
141 *
142 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500143 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700144 *
145 * @return None.
146 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700147inline void
148 getComputerSystem(const std::shared_ptr<AsyncResp>& aResp,
149 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700150{
Ed Tanous6c34de42018-08-29 13:37:36 -0700151 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500152
Ed Tanous6c34de42018-08-29 13:37:36 -0700153 crow::connections::systemBus->async_method_call(
James Feist5bc2dc82019-10-22 14:33:16 -0700154 [aResp, systemHealth](
Ed Tanous6c34de42018-08-29 13:37:36 -0700155 const boost::system::error_code ec,
156 const std::vector<std::pair<
157 std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500158 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
159 subtree) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700160 if (ec)
161 {
162 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700163 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700164 return;
165 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700166 // Iterate over all retrieved ObjectPaths.
167 for (const std::pair<std::string,
168 std::vector<std::pair<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500169 std::string, std::vector<std::string>>>>&
170 object : subtree)
Ed Tanous6c34de42018-08-29 13:37:36 -0700171 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500172 const std::string& path = object.first;
Ed Tanous6c34de42018-08-29 13:37:36 -0700173 BMCWEB_LOG_DEBUG << "Got path: " << path;
174 const std::vector<
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500175 std::pair<std::string, std::vector<std::string>>>&
176 connectionNames = object.second;
Ed Tanous6c34de42018-08-29 13:37:36 -0700177 if (connectionNames.size() < 1)
178 {
179 continue;
180 }
Ed Tanous029573d2019-02-01 10:57:49 -0800181
James Feist5bc2dc82019-10-22 14:33:16 -0700182 auto memoryHealth = std::make_shared<HealthPopulate>(
183 aResp, aResp->res.jsonValue["MemorySummary"]["Status"]);
184
185 auto cpuHealth = std::make_shared<HealthPopulate>(
186 aResp, aResp->res.jsonValue["ProcessorSummary"]["Status"]);
187
188 systemHealth->children.emplace_back(memoryHealth);
189 systemHealth->children.emplace_back(cpuHealth);
190
Ed Tanous029573d2019-02-01 10:57:49 -0800191 // This is not system, so check if it's cpu, dimm, UUID or
192 // BiosVer
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500193 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700194 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500195 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700196 {
Ed Tanous029573d2019-02-01 10:57:49 -0800197 if (interfaceName ==
198 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700199 {
Ed Tanous029573d2019-02-01 10:57:49 -0800200 BMCWEB_LOG_DEBUG
201 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500202
Ed Tanous029573d2019-02-01 10:57:49 -0800203 crow::connections::systemBus->async_method_call(
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500204 [aResp, service{connection.first},
Ed Tanousf23b7292020-10-15 09:41:17 -0700205 path](const boost::system::error_code ec2,
206 const std::vector<
207 std::pair<std::string, VariantType>>&
208 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000209 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800210 {
211 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000212 << "DBUS response error " << ec2;
Ed Tanous029573d2019-02-01 10:57:49 -0800213 messages::internalError(aResp->res);
214 return;
215 }
216 BMCWEB_LOG_DEBUG << "Got "
217 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500218 << " Dimm properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500219
220 if (properties.size() > 0)
Ed Tanous029573d2019-02-01 10:57:49 -0800221 {
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500222 for (const std::pair<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500223 VariantType>&
224 property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700225 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800226 if (property.first !=
227 "MemorySizeInKB")
Ed Tanous6c34de42018-08-29 13:37:36 -0700228 {
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800229 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700230 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500231 const uint32_t* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500232 std::get_if<uint32_t>(
233 &property.second);
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800234 if (value == nullptr)
235 {
236 BMCWEB_LOG_DEBUG
237 << "Find incorrect type of "
238 "MemorySize";
239 continue;
240 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500241 nlohmann::json& totalMemory =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800242 aResp->res
243 .jsonValue["MemorySummar"
244 "y"]
245 ["TotalSystemMe"
246 "moryGiB"];
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500247 uint64_t* preValue =
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800248 totalMemory
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500249 .get_ptr<uint64_t*>();
Cheng C Yang5fd7ba62019-11-28 15:58:08 +0800250 if (preValue == nullptr)
251 {
252 continue;
253 }
254 aResp->res
255 .jsonValue["MemorySummary"]
256 ["TotalSystemMemoryGi"
257 "B"] =
258 *value / (1024 * 1024) +
259 *preValue;
260 aResp->res
261 .jsonValue["MemorySummary"]
262 ["Status"]["State"] =
263 "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700264 }
Ed Tanous029573d2019-02-01 10:57:49 -0800265 }
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500266 else
267 {
268 auto getDimmProperties =
269 [aResp](
270 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000271 ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500272 const std::variant<bool>&
273 dimmState) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000274 if (ec3)
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500275 {
276 BMCWEB_LOG_ERROR
277 << "DBUS response "
278 "error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000279 << ec3;
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500280 return;
281 }
282 updateDimmProperties(aResp,
283 dimmState);
284 };
285 crow::connections::systemBus
286 ->async_method_call(
287 std::move(getDimmProperties),
288 service, path,
289 "org.freedesktop.DBus."
290 "Properties",
291 "Get",
292 "xyz.openbmc_project.State."
293 "Decorator.OperationalStatus",
294 "Functional");
295 }
Ed Tanous029573d2019-02-01 10:57:49 -0800296 },
297 connection.first, path,
298 "org.freedesktop.DBus.Properties", "GetAll",
299 "xyz.openbmc_project.Inventory.Item.Dimm");
James Feist5bc2dc82019-10-22 14:33:16 -0700300
301 memoryHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800302 }
303 else if (interfaceName ==
304 "xyz.openbmc_project.Inventory.Item.Cpu")
305 {
306 BMCWEB_LOG_DEBUG
307 << "Found Cpu, now get its properties.";
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500308
Ed Tanous029573d2019-02-01 10:57:49 -0800309 crow::connections::systemBus->async_method_call(
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500310 [aResp, service{connection.first},
Ed Tanousf23b7292020-10-15 09:41:17 -0700311 path](const boost::system::error_code ec2,
312 const std::vector<
313 std::pair<std::string, VariantType>>&
314 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000315 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800316 {
317 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000318 << "DBUS response error " << ec2;
Ed Tanous029573d2019-02-01 10:57:49 -0800319 messages::internalError(aResp->res);
320 return;
321 }
322 BMCWEB_LOG_DEBUG << "Got "
323 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500324 << " Cpu properties.";
Ed Tanous04a258f2018-10-15 08:00:41 -0700325
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500326 if (properties.size() > 0)
327 {
Zhikui Ren9cf21522020-09-10 11:13:14 -0700328 const uint64_t* processorId = nullptr;
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700329 const std::string* procFamily = nullptr;
330 nlohmann::json& procSummary =
331 aResp->res.jsonValue["ProcessorSumm"
332 "ary"];
333 nlohmann::json& procCount =
334 procSummary["Count"];
335
336 auto procCountPtr = procCount.get_ptr<
337 nlohmann::json::
338 number_integer_t*>();
339 if (procCountPtr == nullptr)
340 {
341 messages::internalError(aResp->res);
342 return;
343 }
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500344 for (const auto& property : properties)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500345 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700346
Zhikui Ren9cf21522020-09-10 11:13:14 -0700347 if (property.first == "Id")
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700348 {
349 processorId =
Zhikui Ren9cf21522020-09-10 11:13:14 -0700350 std::get_if<uint64_t>(
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700351 &property.second);
352 if (nullptr != procFamily)
Ed Tanous3174e4d2020-10-07 11:41:22 -0700353 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700354 break;
Ed Tanous3174e4d2020-10-07 11:41:22 -0700355 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700356 continue;
357 }
358
Zhikui Ren9cf21522020-09-10 11:13:14 -0700359 if (property.first == "Family")
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500360 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700361 procFamily =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500362 std::get_if<std::string>(
363 &property.second);
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700364 if (nullptr != processorId)
Ed Tanous3174e4d2020-10-07 11:41:22 -0700365 {
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700366 break;
Ed Tanous3174e4d2020-10-07 11:41:22 -0700367 }
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700368 continue;
369 }
370 }
James Feistb4b95952019-12-05 15:01:55 -0800371
Zhikui Ren029cc1f2020-08-25 15:21:41 -0700372 if (procFamily != nullptr &&
373 processorId != nullptr)
374 {
375 if (procCountPtr != nullptr &&
376 *processorId != 0)
377 {
378 *procCountPtr += 1;
379 procSummary["Status"]["State"] =
380 "Enabled";
381
382 procSummary["Model"] =
383 *procFamily;
Ed Tanous6c34de42018-08-29 13:37:36 -0700384 }
385 }
Ed Tanous029573d2019-02-01 10:57:49 -0800386 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500387 else
388 {
389 auto getCpuPresenceState =
390 [aResp](
391 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000392 ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500393 const std::variant<bool>&
394 cpuPresenceCheck) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000395 if (ec3)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500396 {
397 BMCWEB_LOG_ERROR
398 << "DBUS response "
399 "error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000400 << ec3;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500401 return;
402 }
403 modifyCpuPresenceState(
404 aResp, cpuPresenceCheck);
405 };
406
407 auto getCpuFunctionalState =
408 [aResp](
409 const boost::system::error_code
Ed Tanouscb13a392020-07-25 19:02:03 +0000410 ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500411 const std::variant<bool>&
412 cpuFunctionalCheck) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000413 if (ec3)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500414 {
415 BMCWEB_LOG_ERROR
416 << "DBUS response "
417 "error "
Ed Tanouscb13a392020-07-25 19:02:03 +0000418 << ec3;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500419 return;
420 }
421 modifyCpuFunctionalState(
422 aResp, cpuFunctionalCheck);
423 };
424 // Get the Presence of CPU
425 crow::connections::systemBus
426 ->async_method_call(
427 std::move(getCpuPresenceState),
428 service, path,
429 "org.freedesktop.DBus."
430 "Properties",
431 "Get",
432 "xyz.openbmc_project.Inventory."
433 "Item",
434 "Present");
435
436 // Get the Functional State
437 crow::connections::systemBus
438 ->async_method_call(
439 std::move(
440 getCpuFunctionalState),
441 service, path,
442 "org.freedesktop.DBus."
443 "Properties",
444 "Get",
445 "xyz.openbmc_project.State."
446 "Decorator."
447 "OperationalStatus",
448 "Functional");
449
450 // Get the MODEL from
451 // xyz.openbmc_project.Inventory.Decorator.Asset
452 // support it later as Model is Empty
453 // currently.
454 }
Ed Tanous029573d2019-02-01 10:57:49 -0800455 },
456 connection.first, path,
457 "org.freedesktop.DBus.Properties", "GetAll",
458 "xyz.openbmc_project.Inventory.Item.Cpu");
James Feist5bc2dc82019-10-22 14:33:16 -0700459
460 cpuHealth->inventory.emplace_back(path);
Ed Tanous029573d2019-02-01 10:57:49 -0800461 }
462 else if (interfaceName ==
463 "xyz.openbmc_project.Common.UUID")
464 {
465 BMCWEB_LOG_DEBUG
466 << "Found UUID, now get its properties.";
467 crow::connections::systemBus->async_method_call(
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500468 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000469 const boost::system::error_code ec3,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500470 const std::vector<
471 std::pair<std::string, VariantType>>&
472 properties) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000473 if (ec3)
Ed Tanous029573d2019-02-01 10:57:49 -0800474 {
475 BMCWEB_LOG_DEBUG
Ed Tanouscb13a392020-07-25 19:02:03 +0000476 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800477 messages::internalError(aResp->res);
478 return;
479 }
480 BMCWEB_LOG_DEBUG << "Got "
481 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500482 << " UUID properties.";
Ed Tanous029573d2019-02-01 10:57:49 -0800483 for (const std::pair<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500484 VariantType>&
485 property : properties)
Ed Tanous029573d2019-02-01 10:57:49 -0800486 {
Ed Tanous029573d2019-02-01 10:57:49 -0800487 if (property.first == "UUID")
488 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500489 const std::string* value =
Patrick Williams8d78b7a2020-05-13 11:24:20 -0500490 std::get_if<std::string>(
491 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700492
Ed Tanous029573d2019-02-01 10:57:49 -0800493 if (value != nullptr)
494 {
495 std::string valueStr = *value;
496 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700497 {
Ed Tanous029573d2019-02-01 10:57:49 -0800498 valueStr.insert(8, 1, '-');
499 valueStr.insert(13, 1, '-');
500 valueStr.insert(18, 1, '-');
501 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700502 }
Ed Tanous029573d2019-02-01 10:57:49 -0800503 BMCWEB_LOG_DEBUG << "UUID = "
504 << valueStr;
505 aResp->res.jsonValue["UUID"] =
506 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700507 }
508 }
Ed Tanous029573d2019-02-01 10:57:49 -0800509 }
510 },
511 connection.first, path,
512 "org.freedesktop.DBus.Properties", "GetAll",
513 "xyz.openbmc_project.Common.UUID");
514 }
515 else if (interfaceName ==
516 "xyz.openbmc_project.Inventory.Item.System")
517 {
518 crow::connections::systemBus->async_method_call(
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500519 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000520 const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500521 const std::vector<
522 std::pair<std::string, VariantType>>&
523 propertiesList) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000524 if (ec2)
Ed Tanous029573d2019-02-01 10:57:49 -0800525 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700526 // doesn't have to include this
527 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800528 return;
529 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500530 BMCWEB_LOG_DEBUG
531 << "Got " << propertiesList.size()
532 << " properties for system";
Ed Tanous029573d2019-02-01 10:57:49 -0800533 for (const std::pair<std::string,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500534 VariantType>&
535 property : propertiesList)
Ed Tanous029573d2019-02-01 10:57:49 -0800536 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500537 const std::string& propertyName =
beccabroekfc5afcf2019-03-05 14:35:15 -0600538 property.first;
539 if ((propertyName == "PartNumber") ||
540 (propertyName == "SerialNumber") ||
541 (propertyName == "Manufacturer") ||
SunnySrivastava19845235d962020-06-30 03:09:00 -0500542 (propertyName == "Model") ||
543 (propertyName == "SubModel"))
Ed Tanous029573d2019-02-01 10:57:49 -0800544 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500545 const std::string* value =
beccabroekfc5afcf2019-03-05 14:35:15 -0600546 std::get_if<std::string>(
547 &property.second);
548 if (value != nullptr)
549 {
550 aResp->res
551 .jsonValue[propertyName] =
552 *value;
553 }
Ed Tanous029573d2019-02-01 10:57:49 -0800554 }
555 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500556
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600557 // Grab the bios version
Gunnar Millsf97ddba2020-08-20 15:57:40 -0500558 fw_util::populateFirmwareInformation(
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600559 aResp, fw_util::biosPurpose,
Gunnar Mills72d566d2020-07-21 12:44:00 -0500560 "BiosVersion", false);
Ed Tanous029573d2019-02-01 10:57:49 -0800561 },
562 connection.first, path,
563 "org.freedesktop.DBus.Properties", "GetAll",
564 "xyz.openbmc_project.Inventory.Decorator."
565 "Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700566
567 crow::connections::systemBus->async_method_call(
568 [aResp](
Ed Tanouscb13a392020-07-25 19:02:03 +0000569 const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500570 const std::variant<std::string>& property) {
Ed Tanouscb13a392020-07-25 19:02:03 +0000571 if (ec2)
James Feiste4a4b9a2019-06-20 14:08:07 -0700572 {
573 // doesn't have to include this
574 // interface
575 return;
576 }
577
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500578 const std::string* value =
James Feiste4a4b9a2019-06-20 14:08:07 -0700579 std::get_if<std::string>(&property);
580 if (value != nullptr)
581 {
582 aResp->res.jsonValue["AssetTag"] =
583 *value;
584 }
585 },
586 connection.first, path,
587 "org.freedesktop.DBus.Properties", "Get",
588 "xyz.openbmc_project.Inventory.Decorator."
589 "AssetTag",
590 "AssetTag");
Ed Tanous6c34de42018-08-29 13:37:36 -0700591 }
592 }
593 }
594 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700595 },
596 "xyz.openbmc_project.ObjectMapper",
597 "/xyz/openbmc_project/object_mapper",
598 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700599 "/xyz/openbmc_project/inventory", int32_t(0),
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500600 std::array<const char*, 5>{
Ed Tanous66173382018-08-15 18:20:59 -0700601 "xyz.openbmc_project.Inventory.Decorator.Asset",
602 "xyz.openbmc_project.Inventory.Item.Cpu",
603 "xyz.openbmc_project.Inventory.Item.Dimm",
604 "xyz.openbmc_project.Inventory.Item.System",
605 "xyz.openbmc_project.Common.UUID",
606 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700607}
608
609/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700610 * @brief Retrieves host state properties over dbus
611 *
612 * @param[in] aResp Shared pointer for completing asynchronous calls.
613 *
614 * @return None.
615 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700616inline void getHostState(const std::shared_ptr<AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700617{
618 BMCWEB_LOG_DEBUG << "Get host information.";
619 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800620 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500621 const std::variant<std::string>& hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700622 if (ec)
623 {
624 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700625 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700626 return;
627 }
Ed Tanous66173382018-08-15 18:20:59 -0700628
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500629 const std::string* s = std::get_if<std::string>(&hostState);
Ed Tanous66173382018-08-15 18:20:59 -0700630 BMCWEB_LOG_DEBUG << "Host state: " << *s;
631 if (s != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700632 {
Ed Tanous66173382018-08-15 18:20:59 -0700633 // Verify Host State
Andrew Geissler94732662019-01-08 19:32:16 -0800634 if (*s == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700635 {
Ed Tanous66173382018-08-15 18:20:59 -0700636 aResp->res.jsonValue["PowerState"] = "On";
637 aResp->res.jsonValue["Status"]["State"] = "Enabled";
638 }
Andrew Geissler83935af2020-02-13 10:24:53 -0600639 else if (*s == "xyz.openbmc_project.State.Host.HostState."
Gunnar Mills8c888602020-05-01 14:25:09 -0500640 "Quiesced")
641 {
642 aResp->res.jsonValue["PowerState"] = "On";
643 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
644 }
645 else if (*s == "xyz.openbmc_project.State.Host.HostState."
Andrew Geissler83935af2020-02-13 10:24:53 -0600646 "DiagnosticMode")
647 {
648 aResp->res.jsonValue["PowerState"] = "On";
649 aResp->res.jsonValue["Status"]["State"] = "InTest";
650 }
Ed Tanous66173382018-08-15 18:20:59 -0700651 else
652 {
653 aResp->res.jsonValue["PowerState"] = "Off";
654 aResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700655 }
656 }
657 },
658 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Ed Tanous66173382018-08-15 18:20:59 -0700659 "org.freedesktop.DBus.Properties", "Get",
660 "xyz.openbmc_project.State.Host", "CurrentHostState");
Ed Tanous6c34de42018-08-29 13:37:36 -0700661}
662
663/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500664 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530665 *
666 * @param[in] dbusSource The boot source in DBUS speak.
667 *
668 * @return Returns as a string, the boot source in Redfish terms. If translation
669 * cannot be done, returns an empty string.
670 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000671inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530672{
673 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
674 {
675 return "None";
676 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700677 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530678 {
679 return "Hdd";
680 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700681 if (dbusSource ==
682 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530683 {
684 return "Cd";
685 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700686 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530687 {
688 return "Pxe";
689 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700690 if (dbusSource ==
691 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700692 {
693 return "Usb";
694 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700695 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530696}
697
698/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500699 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530700 *
701 * @param[in] dbusMode The boot mode in DBUS speak.
702 *
703 * @return Returns as a string, the boot mode in Redfish terms. If translation
704 * cannot be done, returns an empty string.
705 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000706inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530707{
708 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
709 {
710 return "None";
711 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700712 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530713 {
714 return "Diags";
715 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700716 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530717 {
718 return "BiosSetup";
719 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700720 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530721}
722
723/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500724 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530725 *
726 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700727 * @param[out] bootSource The DBus source
728 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530729 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700730 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530731 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700732inline int assignBootParameters(const std::shared_ptr<AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500733 const std::string& rfSource,
734 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530735{
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700736 // The caller has initialized the bootSource and bootMode to:
737 // bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
738 // bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
739 // Only modify the bootSource/bootMode variable needed to achieve the
740 // desired boot action.
741
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530742 if (rfSource == "None")
743 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700744 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530745 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700746 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530747 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700748 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
749 }
750 else if (rfSource == "Hdd")
751 {
752 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
753 }
754 else if (rfSource == "Diags")
755 {
756 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
757 }
758 else if (rfSource == "Cd")
759 {
760 bootSource =
761 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
762 }
763 else if (rfSource == "BiosSetup")
764 {
765 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530766 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700767 else if (rfSource == "Usb")
768 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700769 bootSource =
770 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700771 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530772 else
773 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700774 BMCWEB_LOG_DEBUG << "Invalid property value for "
775 "BootSourceOverrideTarget: "
776 << bootSource;
777 messages::propertyValueNotInList(aResp->res, rfSource,
778 "BootSourceTargetOverride");
779 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530780 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700781 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530782}
783
784/**
785 * @brief Retrieves boot mode over DBUS and fills out the response
786 *
787 * @param[in] aResp Shared pointer for generating response message.
788 * @param[in] bootDbusObj The dbus object to query for boot properties.
789 *
790 * @return None.
791 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700792inline void getBootMode(const std::shared_ptr<AsyncResp>& aResp,
793 const std::string& bootDbusObj)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530794{
795 crow::connections::systemBus->async_method_call(
796 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500797 const std::variant<std::string>& bootMode) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530798 if (ec)
799 {
800 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
801 messages::internalError(aResp->res);
802 return;
803 }
804
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500805 const std::string* bootModeStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530806 std::get_if<std::string>(&bootMode);
807
808 if (!bootModeStr)
809 {
810 messages::internalError(aResp->res);
811 return;
812 }
813
814 BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
815
816 // TODO (Santosh): Do we need to support override mode?
817 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = "Legacy";
818 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
819 "AllowableValues"] = {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700820 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530821
822 if (*bootModeStr !=
823 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
824 {
825 auto rfMode = dbusToRfBootMode(*bootModeStr);
826 if (!rfMode.empty())
827 {
828 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
829 rfMode;
830 }
831 }
832
833 // If the BootSourceOverrideTarget is still "None" at the end,
834 // reset the BootSourceOverrideEnabled to indicate that
835 // overrides are disabled
836 if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] ==
837 "None")
838 {
839 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
840 "Disabled";
841 }
842 },
843 "xyz.openbmc_project.Settings", bootDbusObj,
844 "org.freedesktop.DBus.Properties", "Get",
845 "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
846}
847
848/**
849 * @brief Retrieves boot source over DBUS
850 *
851 * @param[in] aResp Shared pointer for generating response message.
852 * @param[in] oneTimeEnable Boolean to indicate boot properties are one-time.
853 *
854 * @return None.
855 */
Ed Tanousf23b7292020-10-15 09:41:17 -0700856inline void getBootSource(const std::shared_ptr<AsyncResp>& aResp,
857 bool oneTimeEnabled)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530858{
859 std::string bootDbusObj =
860 oneTimeEnabled ? "/xyz/openbmc_project/control/host0/boot/one_time"
861 : "/xyz/openbmc_project/control/host0/boot";
862
863 BMCWEB_LOG_DEBUG << "Is one time: " << oneTimeEnabled;
864 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
865 (oneTimeEnabled) ? "Once" : "Continuous";
866
867 crow::connections::systemBus->async_method_call(
868 [aResp, bootDbusObj](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500869 const std::variant<std::string>& bootSource) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530870 if (ec)
871 {
872 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
873 messages::internalError(aResp->res);
874 return;
875 }
876
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500877 const std::string* bootSourceStr =
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530878 std::get_if<std::string>(&bootSource);
879
880 if (!bootSourceStr)
881 {
882 messages::internalError(aResp->res);
883 return;
884 }
885 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
886
887 auto rfSource = dbusToRfBootSource(*bootSourceStr);
888 if (!rfSource.empty())
889 {
890 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
891 rfSource;
892 }
893 },
894 "xyz.openbmc_project.Settings", bootDbusObj,
895 "org.freedesktop.DBus.Properties", "Get",
896 "xyz.openbmc_project.Control.Boot.Source", "BootSource");
Ed Tanousf23b7292020-10-15 09:41:17 -0700897 getBootMode(aResp, bootDbusObj);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530898}
899
900/**
901 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
902 * get boot source and boot mode.
903 *
904 * @param[in] aResp Shared pointer for generating response message.
905 *
906 * @return None.
907 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700908inline void getBootProperties(const std::shared_ptr<AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530909{
910 BMCWEB_LOG_DEBUG << "Get boot information.";
911
912 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800913 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500914 const std::variant<bool>& oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530915 if (ec)
916 {
917 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
James Feist2a833c72019-07-19 10:17:13 -0700918 // not an error, don't have to have the interface
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530919 return;
920 }
921
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500922 const bool* oneTimePtr = std::get_if<bool>(&oneTime);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530923
924 if (!oneTimePtr)
925 {
926 messages::internalError(aResp->res);
927 return;
928 }
929 getBootSource(aResp, *oneTimePtr);
930 },
931 "xyz.openbmc_project.Settings",
932 "/xyz/openbmc_project/control/host0/boot/one_time",
933 "org.freedesktop.DBus.Properties", "Get",
934 "xyz.openbmc_project.Object.Enable", "Enabled");
935}
936
937/**
Gunnar Millsc0557e12020-06-30 11:26:20 -0500938 * @brief Retrieves the Last Reset Time
939 *
940 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
941 * and power off. Even though this is the "system" Redfish object look at the
942 * chassis D-Bus interface for the LastStateChangeTime since this has the
943 * last power operation time.
944 *
945 * @param[in] aResp Shared pointer for generating response message.
946 *
947 * @return None.
948 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700949inline void getLastResetTime(const std::shared_ptr<AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -0500950{
951 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
952
953 crow::connections::systemBus->async_method_call(
954 [aResp](const boost::system::error_code ec,
955 std::variant<uint64_t>& lastResetTime) {
956 if (ec)
957 {
958 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
959 return;
960 }
961
962 const uint64_t* lastResetTimePtr =
963 std::get_if<uint64_t>(&lastResetTime);
964
965 if (!lastResetTimePtr)
966 {
967 messages::internalError(aResp->res);
968 return;
969 }
970 // LastStateChangeTime is epoch time, in milliseconds
971 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
972 time_t lastResetTimeStamp =
973 static_cast<time_t>(*lastResetTimePtr / 1000);
974
975 // Convert to ISO 8601 standard
976 aResp->res.jsonValue["LastResetTime"] =
977 crow::utility::getDateTime(lastResetTimeStamp);
978 },
979 "xyz.openbmc_project.State.Chassis",
980 "/xyz/openbmc_project/state/chassis0",
981 "org.freedesktop.DBus.Properties", "Get",
982 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime");
983}
984
985/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -0500986 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
987 *
988 * @param[in] aResp Shared pointer for generating response message.
989 *
990 * @return None.
991 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700992inline void getAutomaticRetry(const std::shared_ptr<AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -0500993{
994 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
995
996 crow::connections::systemBus->async_method_call(
997 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500998 std::variant<bool>& autoRebootEnabled) {
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -0500999 if (ec)
1000 {
1001 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1002 return;
1003 }
1004
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001005 const bool* autoRebootEnabledPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001006 std::get_if<bool>(&autoRebootEnabled);
1007
1008 if (!autoRebootEnabledPtr)
1009 {
1010 messages::internalError(aResp->res);
1011 return;
1012 }
1013
1014 BMCWEB_LOG_DEBUG << "Auto Reboot: " << *autoRebootEnabledPtr;
1015 if (*autoRebootEnabledPtr == true)
1016 {
1017 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1018 "RetryAttempts";
1019 // If AutomaticRetry (AutoReboot) is enabled see how many
1020 // attempts are left
1021 crow::connections::systemBus->async_method_call(
Ed Tanouscb13a392020-07-25 19:02:03 +00001022 [aResp](const boost::system::error_code ec2,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001023 std::variant<uint32_t>& autoRebootAttemptsLeft) {
Ed Tanouscb13a392020-07-25 19:02:03 +00001024 if (ec2)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001025 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001026 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001027 return;
1028 }
1029
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001030 const uint32_t* autoRebootAttemptsLeftPtr =
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001031 std::get_if<uint32_t>(&autoRebootAttemptsLeft);
1032
1033 if (!autoRebootAttemptsLeftPtr)
1034 {
1035 messages::internalError(aResp->res);
1036 return;
1037 }
1038
1039 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1040 << *autoRebootAttemptsLeftPtr;
1041
1042 aResp->res
1043 .jsonValue["Boot"]
1044 ["RemainingAutomaticRetryAttempts"] =
1045 *autoRebootAttemptsLeftPtr;
1046 },
1047 "xyz.openbmc_project.State.Host",
1048 "/xyz/openbmc_project/state/host0",
1049 "org.freedesktop.DBus.Properties", "Get",
1050 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1051 "AttemptsLeft");
1052 }
1053 else
1054 {
1055 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1056 "Disabled";
1057 }
1058
1059 // Not on D-Bus. Hardcoded here:
1060 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1061 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001062
1063 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1064 // and RetryAttempts. OpenBMC only supports Disabled and
1065 // RetryAttempts.
1066 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig@Redfish."
1067 "AllowableValues"] = {"Disabled",
1068 "RetryAttempts"};
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001069 },
1070 "xyz.openbmc_project.Settings",
1071 "/xyz/openbmc_project/control/host0/auto_reboot",
1072 "org.freedesktop.DBus.Properties", "Get",
1073 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot");
1074}
1075
1076/**
George Liuc6a620f2020-04-10 17:18:11 +08001077 * @brief Retrieves power restore policy over DBUS.
1078 *
1079 * @param[in] aResp Shared pointer for generating response message.
1080 *
1081 * @return None.
1082 */
Ed Tanousb5a76932020-09-29 16:16:58 -07001083inline void getPowerRestorePolicy(const std::shared_ptr<AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001084{
1085 BMCWEB_LOG_DEBUG << "Get power restore policy";
1086
1087 crow::connections::systemBus->async_method_call(
1088 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001089 std::variant<std::string>& policy) {
George Liuc6a620f2020-04-10 17:18:11 +08001090 if (ec)
1091 {
1092 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1093 return;
1094 }
1095
1096 const boost::container::flat_map<std::string, std::string>
1097 policyMaps = {
1098 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1099 "AlwaysOn",
1100 "AlwaysOn"},
1101 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1102 "AlwaysOff",
1103 "AlwaysOff"},
1104 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1105 "LastState",
1106 "LastState"}};
1107
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001108 const std::string* policyPtr = std::get_if<std::string>(&policy);
George Liuc6a620f2020-04-10 17:18:11 +08001109
1110 if (!policyPtr)
1111 {
1112 messages::internalError(aResp->res);
1113 return;
1114 }
1115
1116 auto policyMapsIt = policyMaps.find(*policyPtr);
1117 if (policyMapsIt == policyMaps.end())
1118 {
1119 messages::internalError(aResp->res);
1120 return;
1121 }
1122
1123 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
1124 },
1125 "xyz.openbmc_project.Settings",
1126 "/xyz/openbmc_project/control/host0/power_restore_policy",
1127 "org.freedesktop.DBus.Properties", "Get",
1128 "xyz.openbmc_project.Control.Power.RestorePolicy",
1129 "PowerRestorePolicy");
1130}
1131
1132/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301133 * @brief Sets boot properties into DBUS object(s).
1134 *
1135 * @param[in] aResp Shared pointer for generating response message.
1136 * @param[in] oneTimeEnabled Is "one-time" setting already enabled.
1137 * @param[in] bootSource The boot source to set.
1138 * @param[in] bootEnable The source override "enable" to set.
1139 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001140 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301141 */
Ed Tanous23a21a12020-07-25 04:45:05 +00001142inline void setBootModeOrSource(std::shared_ptr<AsyncResp> aResp,
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301143 bool oneTimeEnabled,
Ed Tanousf23b7292020-10-15 09:41:17 -07001144 const std::optional<std::string>& bootSource,
1145 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301146{
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001147 std::string bootSourceStr =
1148 "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
1149 std::string bootModeStr =
1150 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301151 bool oneTimeSetting = oneTimeEnabled;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001152 bool useBootSource = true;
1153
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301154 // Validate incoming parameters
1155 if (bootEnable)
1156 {
1157 if (*bootEnable == "Once")
1158 {
1159 oneTimeSetting = true;
1160 }
1161 else if (*bootEnable == "Continuous")
1162 {
1163 oneTimeSetting = false;
1164 }
1165 else if (*bootEnable == "Disabled")
1166 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001167 BMCWEB_LOG_DEBUG << "Boot source override will be disabled";
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301168 oneTimeSetting = false;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001169 useBootSource = false;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301170 }
1171 else
1172 {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301173 BMCWEB_LOG_DEBUG << "Unsupported value for "
1174 "BootSourceOverrideEnabled: "
1175 << *bootEnable;
1176 messages::propertyValueNotInList(aResp->res, *bootEnable,
1177 "BootSourceOverrideEnabled");
1178 return;
1179 }
1180 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301181
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001182 if (bootSource && useBootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301183 {
1184 // Source target specified
1185 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1186 // Figure out which DBUS interface and property to use
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001187 if (assignBootParameters(aResp, *bootSource, bootSourceStr,
1188 bootModeStr))
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301189 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001190 BMCWEB_LOG_DEBUG
1191 << "Invalid property value for BootSourceOverrideTarget: "
1192 << *bootSource;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301193 messages::propertyValueNotInList(aResp->res, *bootSource,
1194 "BootSourceTargetOverride");
1195 return;
1196 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001197 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301198
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001199 // Act on validated parameters
1200 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1201 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001202 const char* bootObj =
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001203 oneTimeSetting ? "/xyz/openbmc_project/control/host0/boot/one_time"
1204 : "/xyz/openbmc_project/control/host0/boot";
1205
1206 crow::connections::systemBus->async_method_call(
1207 [aResp](const boost::system::error_code ec) {
1208 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301209 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001210 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1211 messages::internalError(aResp->res);
1212 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301213 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001214 BMCWEB_LOG_DEBUG << "Boot source update done.";
1215 },
1216 "xyz.openbmc_project.Settings", bootObj,
1217 "org.freedesktop.DBus.Properties", "Set",
1218 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1219 std::variant<std::string>(bootSourceStr));
1220
1221 crow::connections::systemBus->async_method_call(
1222 [aResp](const boost::system::error_code ec) {
1223 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301224 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001225 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1226 messages::internalError(aResp->res);
1227 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301228 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001229 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1230 },
1231 "xyz.openbmc_project.Settings", bootObj,
1232 "org.freedesktop.DBus.Properties", "Set",
1233 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1234 std::variant<std::string>(bootModeStr));
1235
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301236 crow::connections::systemBus->async_method_call(
1237 [aResp{std::move(aResp)}](const boost::system::error_code ec) {
1238 if (ec)
1239 {
1240 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1241 messages::internalError(aResp->res);
1242 return;
1243 }
1244 BMCWEB_LOG_DEBUG << "Boot enable update done.";
1245 },
1246 "xyz.openbmc_project.Settings",
1247 "/xyz/openbmc_project/control/host0/boot/one_time",
1248 "org.freedesktop.DBus.Properties", "Set",
1249 "xyz.openbmc_project.Object.Enable", "Enabled",
1250 std::variant<bool>(oneTimeSetting));
1251}
1252
1253/**
1254 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
1255 * set boot source/boot mode properties.
1256 *
1257 * @param[in] aResp Shared pointer for generating response message.
1258 * @param[in] bootSource The boot source from incoming RF request.
1259 * @param[in] bootEnable The boot override enable from incoming RF request.
1260 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001261 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301262 */
Ed Tanousb5a76932020-09-29 16:16:58 -07001263inline void setBootSourceProperties(const std::shared_ptr<AsyncResp>& aResp,
Gunnar Mills69f35302020-05-17 16:06:31 -05001264 std::optional<std::string> bootSource,
1265 std::optional<std::string> bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301266{
1267 BMCWEB_LOG_DEBUG << "Set boot information.";
1268
1269 crow::connections::systemBus->async_method_call(
Johnathan Mantey265c1602019-08-08 11:02:51 -07001270 [aResp, bootSource{std::move(bootSource)},
Patrick Williams19bd78d2020-05-13 17:38:24 -05001271 bootEnable{std::move(bootEnable)}](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001272 const std::variant<bool>& oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301273 if (ec)
1274 {
1275 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1276 messages::internalError(aResp->res);
1277 return;
1278 }
1279
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001280 const bool* oneTimePtr = std::get_if<bool>(&oneTime);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301281
1282 if (!oneTimePtr)
1283 {
1284 messages::internalError(aResp->res);
1285 return;
1286 }
1287
1288 BMCWEB_LOG_DEBUG << "Got one time: " << *oneTimePtr;
1289
Ed Tanousf23b7292020-10-15 09:41:17 -07001290 setBootModeOrSource(aResp, *oneTimePtr, bootSource, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301291 },
1292 "xyz.openbmc_project.Settings",
1293 "/xyz/openbmc_project/control/host0/boot/one_time",
1294 "org.freedesktop.DBus.Properties", "Get",
1295 "xyz.openbmc_project.Object.Enable", "Enabled");
1296}
1297
George Liuc6a620f2020-04-10 17:18:11 +08001298/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001299 * @brief Sets AssetTag
1300 *
1301 * @param[in] aResp Shared pointer for generating response message.
1302 * @param[in] assetTag "AssetTag" from request.
1303 *
1304 * @return None.
1305 */
1306inline void setAssetTag(const std::shared_ptr<AsyncResp>& aResp,
1307 const std::string& assetTag)
1308{
1309 crow::connections::systemBus->async_method_call(
1310 [aResp, assetTag](
1311 const boost::system::error_code ec,
1312 const std::vector<std::pair<
1313 std::string,
1314 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
1315 subtree) {
1316 if (ec)
1317 {
1318 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1319 messages::internalError(aResp->res);
1320 return;
1321 }
1322 if (subtree.size() == 0)
1323 {
1324 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1325 messages::internalError(aResp->res);
1326 return;
1327 }
1328 // Assume only 1 system D-Bus object
1329 // Throw an error if there is more than 1
1330 if (subtree.size() > 1)
1331 {
1332 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1333 messages::internalError(aResp->res);
1334 return;
1335 }
1336 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1337 {
1338 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1339 messages::internalError(aResp->res);
1340 return;
1341 }
1342
1343 const std::string& path = subtree[0].first;
1344 const std::string& service = subtree[0].second.begin()->first;
1345
1346 if (service.empty())
1347 {
1348 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1349 messages::internalError(aResp->res);
1350 return;
1351 }
1352
1353 crow::connections::systemBus->async_method_call(
1354 [aResp](const boost::system::error_code ec2) {
1355 if (ec2)
1356 {
1357 BMCWEB_LOG_DEBUG
1358 << "D-Bus response error on AssetTag Set " << ec2;
1359 messages::internalError(aResp->res);
1360 return;
1361 }
1362 },
1363 service, path, "org.freedesktop.DBus.Properties", "Set",
1364 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1365 std::variant<std::string>(assetTag));
1366 },
1367 "xyz.openbmc_project.ObjectMapper",
1368 "/xyz/openbmc_project/object_mapper",
1369 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1370 "/xyz/openbmc_project/inventory", int32_t(0),
1371 std::array<const char*, 1>{
1372 "xyz.openbmc_project.Inventory.Item.System"});
1373}
1374
1375/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001376 * @brief Sets automaticRetry (Auto Reboot)
1377 *
1378 * @param[in] aResp Shared pointer for generating response message.
1379 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1380 *
1381 * @return None.
1382 */
Ed Tanousb5a76932020-09-29 16:16:58 -07001383inline void setAutomaticRetry(const std::shared_ptr<AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001384 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001385{
1386 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1387
1388 // OpenBMC only supports "Disabled" and "RetryAttempts".
1389 bool autoRebootEnabled;
1390
1391 if (automaticRetryConfig == "Disabled")
1392 {
1393 autoRebootEnabled = false;
1394 }
1395 else if (automaticRetryConfig == "RetryAttempts")
1396 {
1397 autoRebootEnabled = true;
1398 }
1399 else
1400 {
1401 BMCWEB_LOG_DEBUG << "Invalid property value for "
1402 "AutomaticRetryConfig: "
1403 << automaticRetryConfig;
1404 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1405 "AutomaticRetryConfig");
1406 return;
1407 }
1408
1409 crow::connections::systemBus->async_method_call(
1410 [aResp](const boost::system::error_code ec) {
1411 if (ec)
1412 {
1413 messages::internalError(aResp->res);
1414 return;
1415 }
1416 },
1417 "xyz.openbmc_project.Settings",
1418 "/xyz/openbmc_project/control/host0/auto_reboot",
1419 "org.freedesktop.DBus.Properties", "Set",
1420 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1421 std::variant<bool>(autoRebootEnabled));
1422}
1423
1424/**
George Liuc6a620f2020-04-10 17:18:11 +08001425 * @brief Sets power restore policy properties.
1426 *
1427 * @param[in] aResp Shared pointer for generating response message.
1428 * @param[in] policy power restore policy properties from request.
1429 *
1430 * @return None.
1431 */
Ed Tanousb5a76932020-09-29 16:16:58 -07001432inline void setPowerRestorePolicy(const std::shared_ptr<AsyncResp>& aResp,
George Liuc6a620f2020-04-10 17:18:11 +08001433 std::optional<std::string> policy)
1434{
1435 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1436
1437 const boost::container::flat_map<std::string, std::string> policyMaps = {
1438 {"AlwaysOn", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1439 "AlwaysOn"},
1440 {"AlwaysOff", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1441 "AlwaysOff"},
1442 {"LastState", "xyz.openbmc_project.Control.Power.RestorePolicy.Policy."
1443 "LastState"}};
1444
1445 std::string powerRestorPolicy;
1446
1447 auto policyMapsIt = policyMaps.find(*policy);
1448 if (policyMapsIt == policyMaps.end())
1449 {
1450 messages::internalError(aResp->res);
1451 return;
1452 }
1453
1454 powerRestorPolicy = policyMapsIt->second;
1455
1456 crow::connections::systemBus->async_method_call(
1457 [aResp](const boost::system::error_code ec) {
1458 if (ec)
1459 {
1460 messages::internalError(aResp->res);
1461 return;
1462 }
1463 },
1464 "xyz.openbmc_project.Settings",
1465 "/xyz/openbmc_project/control/host0/power_restore_policy",
1466 "org.freedesktop.DBus.Properties", "Set",
1467 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1468 std::variant<std::string>(powerRestorPolicy));
1469}
1470
AppaRao Pulia6349912019-10-18 17:16:08 +05301471#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1472/**
1473 * @brief Retrieves provisioning status
1474 *
1475 * @param[in] aResp Shared pointer for completing asynchronous calls.
1476 *
1477 * @return None.
1478 */
Ed Tanous23a21a12020-07-25 04:45:05 +00001479inline void getProvisioningStatus(std::shared_ptr<AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301480{
1481 BMCWEB_LOG_DEBUG << "Get OEM information.";
1482 crow::connections::systemBus->async_method_call(
1483 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001484 const std::vector<std::pair<std::string, VariantType>>&
1485 propertiesList) {
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301486 nlohmann::json& oemPFR =
1487 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
James Feist50626f42020-09-23 14:40:47 -07001488 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1489 "#OemComputerSystem.OpenBmc";
1490 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
1491
AppaRao Pulia6349912019-10-18 17:16:08 +05301492 if (ec)
1493 {
1494 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
AppaRao Pulib99fb1a2020-07-08 16:42:48 +05301495 // not an error, don't have to have the interface
1496 oemPFR["ProvisioningStatus"] = "NotProvisioned";
AppaRao Pulia6349912019-10-18 17:16:08 +05301497 return;
1498 }
1499
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001500 const bool* provState = nullptr;
1501 const bool* lockState = nullptr;
1502 for (const std::pair<std::string, VariantType>& property :
AppaRao Pulia6349912019-10-18 17:16:08 +05301503 propertiesList)
1504 {
1505 if (property.first == "UfmProvisioned")
1506 {
1507 provState = std::get_if<bool>(&property.second);
1508 }
1509 else if (property.first == "UfmLocked")
1510 {
1511 lockState = std::get_if<bool>(&property.second);
1512 }
1513 }
1514
1515 if ((provState == nullptr) || (lockState == nullptr))
1516 {
1517 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1518 messages::internalError(aResp->res);
1519 return;
1520 }
1521
AppaRao Pulia6349912019-10-18 17:16:08 +05301522 if (*provState == true)
1523 {
1524 if (*lockState == true)
1525 {
1526 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
1527 }
1528 else
1529 {
1530 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
1531 }
1532 }
1533 else
1534 {
1535 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1536 }
1537 },
1538 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1539 "org.freedesktop.DBus.Properties", "GetAll",
1540 "xyz.openbmc_project.PFR.Attributes");
1541}
1542#endif
1543
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301544/**
Yong Li51709ff2019-09-30 14:13:04 +08001545 * @brief Translates watchdog timeout action DBUS property value to redfish.
1546 *
1547 * @param[in] dbusAction The watchdog timeout action in D-BUS.
1548 *
1549 * @return Returns as a string, the timeout action in Redfish terms. If
1550 * translation cannot be done, returns an empty string.
1551 */
Ed Tanous23a21a12020-07-25 04:45:05 +00001552inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08001553{
1554 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
1555 {
1556 return "None";
1557 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07001558 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08001559 {
1560 return "ResetSystem";
1561 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07001562 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08001563 {
1564 return "PowerDown";
1565 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07001566 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08001567 {
1568 return "PowerCycle";
1569 }
1570
1571 return "";
1572}
1573
1574/**
Yong Lic45f0082019-10-10 14:19:01 +08001575 *@brief Translates timeout action from Redfish to DBUS property value.
1576 *
1577 *@param[in] rfAction The timeout action in Redfish.
1578 *
1579 *@return Returns as a string, the time_out action as expected by DBUS.
1580 *If translation cannot be done, returns an empty string.
1581 */
1582
Ed Tanous23a21a12020-07-25 04:45:05 +00001583inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08001584{
1585 if (rfAction == "None")
1586 {
1587 return "xyz.openbmc_project.State.Watchdog.Action.None";
1588 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07001589 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08001590 {
1591 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
1592 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07001593 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08001594 {
1595 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
1596 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07001597 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08001598 {
1599 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
1600 }
1601
1602 return "";
1603}
1604
1605/**
Yong Li51709ff2019-09-30 14:13:04 +08001606 * @brief Retrieves host watchdog timer properties over DBUS
1607 *
1608 * @param[in] aResp Shared pointer for completing asynchronous calls.
1609 *
1610 * @return None.
1611 */
Ed Tanousb5a76932020-09-29 16:16:58 -07001612inline void getHostWatchdogTimer(const std::shared_ptr<AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08001613{
1614 BMCWEB_LOG_DEBUG << "Get host watchodg";
1615 crow::connections::systemBus->async_method_call(
1616 [aResp](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001617 PropertiesType& properties) {
Yong Li51709ff2019-09-30 14:13:04 +08001618 if (ec)
1619 {
1620 // watchdog service is stopped
1621 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1622 return;
1623 }
1624
1625 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
1626
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001627 nlohmann::json& hostWatchdogTimer =
Yong Li51709ff2019-09-30 14:13:04 +08001628 aResp->res.jsonValue["HostWatchdogTimer"];
1629
1630 // watchdog service is running/enabled
1631 hostWatchdogTimer["Status"]["State"] = "Enabled";
1632
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001633 for (const auto& property : properties)
Yong Li51709ff2019-09-30 14:13:04 +08001634 {
1635 BMCWEB_LOG_DEBUG << "prop=" << property.first;
1636 if (property.first == "Enabled")
1637 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001638 const bool* state = std::get_if<bool>(&property.second);
Yong Li51709ff2019-09-30 14:13:04 +08001639
1640 if (!state)
1641 {
1642 messages::internalError(aResp->res);
1643 continue;
1644 }
1645
1646 hostWatchdogTimer["FunctionEnabled"] = *state;
1647 }
1648 else if (property.first == "ExpireAction")
1649 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001650 const std::string* s =
Yong Li51709ff2019-09-30 14:13:04 +08001651 std::get_if<std::string>(&property.second);
1652 if (!s)
1653 {
1654 messages::internalError(aResp->res);
1655 continue;
1656 }
1657
1658 std::string action = dbusToRfWatchdogAction(*s);
1659 if (action.empty())
1660 {
1661 messages::internalError(aResp->res);
1662 continue;
1663 }
1664 hostWatchdogTimer["TimeoutAction"] = action;
1665 }
1666 }
1667 },
1668 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
1669 "org.freedesktop.DBus.Properties", "GetAll",
1670 "xyz.openbmc_project.State.Watchdog");
1671}
1672
1673/**
Yong Lic45f0082019-10-10 14:19:01 +08001674 * @brief Sets Host WatchDog Timer properties.
1675 *
1676 * @param[in] aResp Shared pointer for generating response message.
1677 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
1678 * RF request.
1679 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
1680 *
1681 * @return None.
1682 */
Ed Tanousb5a76932020-09-29 16:16:58 -07001683inline void setWDTProperties(const std::shared_ptr<AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08001684 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001685 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08001686{
1687 BMCWEB_LOG_DEBUG << "Set host watchdog";
1688
1689 if (wdtTimeOutAction)
1690 {
1691 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
1692 // check if TimeOut Action is Valid
1693 if (wdtTimeOutActStr.empty())
1694 {
1695 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
1696 << *wdtTimeOutAction;
1697 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
1698 "TimeoutAction");
1699 return;
1700 }
1701
1702 crow::connections::systemBus->async_method_call(
1703 [aResp](const boost::system::error_code ec) {
1704 if (ec)
1705 {
1706 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1707 messages::internalError(aResp->res);
1708 return;
1709 }
1710 },
1711 "xyz.openbmc_project.Watchdog",
1712 "/xyz/openbmc_project/watchdog/host0",
1713 "org.freedesktop.DBus.Properties", "Set",
1714 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
1715 std::variant<std::string>(wdtTimeOutActStr));
1716 }
1717
1718 if (wdtEnable)
1719 {
1720 crow::connections::systemBus->async_method_call(
1721 [aResp](const boost::system::error_code ec) {
1722 if (ec)
1723 {
1724 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1725 messages::internalError(aResp->res);
1726 return;
1727 }
1728 },
1729 "xyz.openbmc_project.Watchdog",
1730 "/xyz/openbmc_project/watchdog/host0",
1731 "org.freedesktop.DBus.Properties", "Set",
1732 "xyz.openbmc_project.State.Watchdog", "Enabled",
1733 std::variant<bool>(*wdtEnable));
1734 }
1735}
1736
1737/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001738 * SystemsCollection derived class for delivering ComputerSystems Collection
1739 * Schema
1740 */
Ed Tanous1abe55e2018-09-05 08:30:59 -07001741class SystemsCollection : public Node
1742{
1743 public:
Ed Tanous52cc1122020-07-18 13:51:21 -07001744 SystemsCollection(App& app) : Node(app, "/redfish/v1/Systems/")
Ed Tanous1abe55e2018-09-05 08:30:59 -07001745 {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001746 entityPrivileges = {
1747 {boost::beast::http::verb::get, {{"Login"}}},
1748 {boost::beast::http::verb::head, {{"Login"}}},
1749 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1750 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1751 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1752 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1753 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001754
Ed Tanous1abe55e2018-09-05 08:30:59 -07001755 private:
Ed Tanouscb13a392020-07-25 19:02:03 +00001756 void doGet(crow::Response& res, const crow::Request&,
1757 const std::vector<std::string>&) override
Ed Tanous1abe55e2018-09-05 08:30:59 -07001758 {
Sunitha Harish462023a2020-02-19 08:34:59 -06001759 std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous0f74e642018-11-12 15:17:05 -08001760 res.jsonValue["@odata.type"] =
1761 "#ComputerSystemCollection.ComputerSystemCollection";
1762 res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
Ed Tanous0f74e642018-11-12 15:17:05 -08001763 res.jsonValue["Name"] = "Computer System Collection";
Sunitha Harish462023a2020-02-19 08:34:59 -06001764
1765 crow::connections::systemBus->async_method_call(
1766 [asyncResp](const boost::system::error_code ec,
Ed Tanouscb13a392020-07-25 19:02:03 +00001767 const std::variant<std::string>& /*hostName*/) {
Ed Tanous2c70f802020-09-28 14:29:23 -07001768 nlohmann::json& ifaceArray =
Sunitha Harish462023a2020-02-19 08:34:59 -06001769 asyncResp->res.jsonValue["Members"];
Ed Tanous2c70f802020-09-28 14:29:23 -07001770 ifaceArray = nlohmann::json::array();
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001771 auto& count = asyncResp->res.jsonValue["Members@odata.count"];
Sunitha Harish462023a2020-02-19 08:34:59 -06001772 count = 0;
Ed Tanous2c70f802020-09-28 14:29:23 -07001773 ifaceArray.push_back(
Ed Tanouscb13a392020-07-25 19:02:03 +00001774 {{"@odata.id", "/redfish/v1/Systems/system"}});
1775 if (!ec)
Sunitha Harish462023a2020-02-19 08:34:59 -06001776 {
Ed Tanouscb13a392020-07-25 19:02:03 +00001777 BMCWEB_LOG_DEBUG << "Hypervisor is available";
Ed Tanous2c70f802020-09-28 14:29:23 -07001778 ifaceArray.push_back(
Ed Tanouscb13a392020-07-25 19:02:03 +00001779 {{"@odata.id", "/redfish/v1/Systems/hypervisor"}});
Ed Tanous2c70f802020-09-28 14:29:23 -07001780 count = ifaceArray.size();
Sunitha Harish462023a2020-02-19 08:34:59 -06001781 return;
1782 }
Sunitha Harish462023a2020-02-19 08:34:59 -06001783 },
Sunitha Harish8e651fb2020-06-17 06:06:25 -05001784 "xyz.openbmc_project.Settings",
1785 "/xyz/openbmc_project/network/hypervisor",
Sunitha Harish462023a2020-02-19 08:34:59 -06001786 "org.freedesktop.DBus.Properties", "Get",
1787 "xyz.openbmc_project.Network.SystemConfiguration", "HostName");
Ed Tanous1abe55e2018-09-05 08:30:59 -07001788 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001789};
1790
1791/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07001792 * SystemActionsReset class supports handle POST method for Reset action.
1793 * The class retrieves and sends data directly to D-Bus.
1794 */
1795class SystemActionsReset : public Node
1796{
1797 public:
Ed Tanous52cc1122020-07-18 13:51:21 -07001798 SystemActionsReset(App& app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001799 Node(app, "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanouscc340dd2018-08-29 13:43:38 -07001800 {
1801 entityPrivileges = {
1802 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1803 }
1804
1805 private:
1806 /**
1807 * Function handles POST method request.
1808 * Analyzes POST body message before sends Reset request data to D-Bus.
1809 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001810 void doPost(crow::Response& res, const crow::Request& req,
Ed Tanouscb13a392020-07-25 19:02:03 +00001811 const std::vector<std::string>&) override
Ed Tanouscc340dd2018-08-29 13:43:38 -07001812 {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001813 auto asyncResp = std::make_shared<AsyncResp>(res);
1814
1815 std::string resetType;
1816 if (!json_util::readJson(req, res, "ResetType", resetType))
Ed Tanouscc340dd2018-08-29 13:43:38 -07001817 {
1818 return;
1819 }
1820
Jason M. Billsd22c8392019-06-03 13:59:03 -07001821 // Get the command and host vs. chassis
Ed Tanous9712f8a2018-09-21 13:38:49 -07001822 std::string command;
Jason M. Billsd22c8392019-06-03 13:59:03 -07001823 bool hostCommand;
Ed Tanousd4d25792020-09-29 15:15:03 -07001824 if ((resetType == "On") || (resetType == "ForceOn"))
Ed Tanous9712f8a2018-09-21 13:38:49 -07001825 {
1826 command = "xyz.openbmc_project.State.Host.Transition.On";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001827 hostCommand = true;
1828 }
1829 else if (resetType == "ForceOff")
1830 {
1831 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
1832 hostCommand = false;
1833 }
Jason M. Billsd22c8392019-06-03 13:59:03 -07001834 else if (resetType == "ForceRestart")
1835 {
Jason M. Bills86a08512020-02-04 13:15:49 -08001836 command =
1837 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
1838 hostCommand = true;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001839 }
1840 else if (resetType == "GracefulShutdown")
1841 {
1842 command = "xyz.openbmc_project.State.Host.Transition.Off";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001843 hostCommand = true;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001844 }
1845 else if (resetType == "GracefulRestart")
1846 {
Jason M. Bills86a08512020-02-04 13:15:49 -08001847 command =
1848 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001849 hostCommand = true;
1850 }
1851 else if (resetType == "PowerCycle")
1852 {
Jason M. Bills86a08512020-02-04 13:15:49 -08001853 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
1854 hostCommand = true;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001855 }
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001856 else if (resetType == "Nmi")
1857 {
1858 doNMI(asyncResp);
1859 return;
1860 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001861 else
1862 {
Jason M. Billsf12894f2018-10-09 12:45:45 -07001863 messages::actionParameterUnknown(res, "Reset", resetType);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001864 return;
1865 }
1866
Jason M. Billsd22c8392019-06-03 13:59:03 -07001867 if (hostCommand)
1868 {
1869 crow::connections::systemBus->async_method_call(
1870 [asyncResp, resetType](const boost::system::error_code ec) {
1871 if (ec)
1872 {
1873 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1874 if (ec.value() == boost::asio::error::invalid_argument)
1875 {
1876 messages::actionParameterNotSupported(
1877 asyncResp->res, resetType, "Reset");
1878 }
1879 else
1880 {
1881 messages::internalError(asyncResp->res);
1882 }
1883 return;
1884 }
1885 messages::success(asyncResp->res);
1886 },
1887 "xyz.openbmc_project.State.Host",
1888 "/xyz/openbmc_project/state/host0",
1889 "org.freedesktop.DBus.Properties", "Set",
1890 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
1891 std::variant<std::string>{command});
1892 }
1893 else
1894 {
1895 crow::connections::systemBus->async_method_call(
1896 [asyncResp, resetType](const boost::system::error_code ec) {
1897 if (ec)
1898 {
1899 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1900 if (ec.value() == boost::asio::error::invalid_argument)
1901 {
1902 messages::actionParameterNotSupported(
1903 asyncResp->res, resetType, "Reset");
1904 }
1905 else
1906 {
1907 messages::internalError(asyncResp->res);
1908 }
1909 return;
1910 }
1911 messages::success(asyncResp->res);
1912 },
1913 "xyz.openbmc_project.State.Chassis",
1914 "/xyz/openbmc_project/state/chassis0",
1915 "org.freedesktop.DBus.Properties", "Set",
1916 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
1917 std::variant<std::string>{command});
1918 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07001919 }
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001920 /**
1921 * Function transceives data with dbus directly.
1922 */
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001923 void doNMI(const std::shared_ptr<AsyncResp>& asyncResp)
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001924 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001925 constexpr char const* serviceName =
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001926 "xyz.openbmc_project.Control.Host.NMI";
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001927 constexpr char const* objectPath =
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001928 "/xyz/openbmc_project/control/host0/nmi";
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001929 constexpr char const* interfaceName =
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001930 "xyz.openbmc_project.Control.Host.NMI";
Gunnar Mills1214b7e2020-06-04 10:11:30 -05001931 constexpr char const* method = "NMI";
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001932
1933 crow::connections::systemBus->async_method_call(
1934 [asyncResp](const boost::system::error_code ec) {
1935 if (ec)
1936 {
1937 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
1938 messages::internalError(asyncResp->res);
1939 return;
1940 }
1941 messages::success(asyncResp->res);
1942 },
1943 serviceName, objectPath, interfaceName, method);
1944 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07001945};
1946
1947/**
Ed Tanous66173382018-08-15 18:20:59 -07001948 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001949 */
Ed Tanous1abe55e2018-09-05 08:30:59 -07001950class Systems : public Node
1951{
1952 public:
1953 /*
1954 * Default Constructor
1955 */
Ed Tanous52cc1122020-07-18 13:51:21 -07001956 Systems(App& app) : Node(app, "/redfish/v1/Systems/system/")
Ed Tanous1abe55e2018-09-05 08:30:59 -07001957 {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001958 entityPrivileges = {
1959 {boost::beast::http::verb::get, {{"Login"}}},
1960 {boost::beast::http::verb::head, {{"Login"}}},
1961 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1962 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1963 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1964 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001965 }
1966
Ed Tanous1abe55e2018-09-05 08:30:59 -07001967 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -07001968 /**
1969 * Functions triggers appropriate requests on DBus
1970 */
Ed Tanouscb13a392020-07-25 19:02:03 +00001971 void doGet(crow::Response& res, const crow::Request&,
1972 const std::vector<std::string>&) override
Ed Tanous1abe55e2018-09-05 08:30:59 -07001973 {
Gunnar Millsc0557e12020-06-30 11:26:20 -05001974 res.jsonValue["@odata.type"] = "#ComputerSystem.v1_12_0.ComputerSystem";
Gunnar Mills450a25c2020-04-14 21:34:07 -05001975 res.jsonValue["Name"] = "system";
Ed Tanous029573d2019-02-01 10:57:49 -08001976 res.jsonValue["Id"] = "system";
Ed Tanous0f74e642018-11-12 15:17:05 -08001977 res.jsonValue["SystemType"] = "Physical";
1978 res.jsonValue["Description"] = "Computer System";
Ed Tanous0f74e642018-11-12 15:17:05 -08001979 res.jsonValue["ProcessorSummary"]["Count"] = 0;
1980 res.jsonValue["ProcessorSummary"]["Status"]["State"] = "Disabled";
Cheng C Yang5fd7ba62019-11-28 15:58:08 +08001981 res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] = uint64_t(0);
Ed Tanous0f74e642018-11-12 15:17:05 -08001982 res.jsonValue["MemorySummary"]["Status"]["State"] = "Disabled";
Ed Tanous029573d2019-02-01 10:57:49 -08001983 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07001984
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001985 res.jsonValue["Processors"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001986 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001987 res.jsonValue["Memory"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001988 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
Nikhil Potadea25aecc2019-08-23 16:35:26 -07001989 res.jsonValue["Storage"] = {
1990 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08001991
Ed Tanouscc340dd2018-08-29 13:43:38 -07001992 res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
1993 {"target",
Ed Tanous029573d2019-02-01 10:57:49 -08001994 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05301995 {"@Redfish.ActionInfo",
1996 "/redfish/v1/Systems/system/ResetActionInfo"}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001997
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001998 res.jsonValue["LogServices"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001999 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002000
Carol Wangd82a3ac2019-11-21 13:56:38 +08002001 res.jsonValue["Bios"] = {
2002 {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
2003
Jennifer Leec5d03ff2019-03-08 15:42:58 -08002004 res.jsonValue["Links"]["ManagedBy"] = {
2005 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
2006
2007 res.jsonValue["Status"] = {
2008 {"Health", "OK"},
2009 {"State", "Enabled"},
2010 };
Ed Tanousa0803ef2018-08-29 13:29:23 -07002011 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -07002012
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002013 constexpr const std::array<const char*, 4> inventoryForSystems = {
James Feistb49ac872019-05-21 15:12:01 -07002014 "xyz.openbmc_project.Inventory.Item.Dimm",
James Feist2ad9c2f2019-10-29 16:26:48 -07002015 "xyz.openbmc_project.Inventory.Item.Cpu",
James Feiste284a7c2019-11-20 16:20:23 -08002016 "xyz.openbmc_project.Inventory.Item.Drive",
2017 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002018
2019 auto health = std::make_shared<HealthPopulate>(asyncResp);
2020 crow::connections::systemBus->async_method_call(
2021 [health](const boost::system::error_code ec,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002022 std::vector<std::string>& resp) {
James Feistb49ac872019-05-21 15:12:01 -07002023 if (ec)
2024 {
2025 // no inventory
2026 return;
2027 }
2028
2029 health->inventory = std::move(resp);
2030 },
2031 "xyz.openbmc_project.ObjectMapper",
2032 "/xyz/openbmc_project/object_mapper",
2033 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2034 int32_t(0), inventoryForSystems);
2035
2036 health->populate();
2037
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002038 getMainChassisId(asyncResp, [](const std::string& chassisId,
Ed Tanousb5a76932020-09-29 16:16:58 -07002039 const std::shared_ptr<AsyncResp>& aRsp) {
Jennifer Leec5d03ff2019-03-08 15:42:58 -08002040 aRsp->res.jsonValue["Links"]["Chassis"] = {
2041 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
2042 });
AppaRao Pulia3002222019-11-12 21:32:59 +05302043
2044 getIndicatorLedState(asyncResp);
James Feist5bc2dc82019-10-22 14:33:16 -07002045 getComputerSystem(asyncResp, health);
Ed Tanous6c34de42018-08-29 13:37:36 -07002046 getHostState(asyncResp);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302047 getBootProperties(asyncResp);
Jason M. Billsadbe1922019-10-14 15:44:35 -07002048 getPCIeDeviceList(asyncResp, "PCIeDevices");
Yong Li51709ff2019-09-30 14:13:04 +08002049 getHostWatchdogTimer(asyncResp);
George Liuc6a620f2020-04-10 17:18:11 +08002050 getPowerRestorePolicy(asyncResp);
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05002051 getAutomaticRetry(asyncResp);
Gunnar Millsc0557e12020-06-30 11:26:20 -05002052 getLastResetTime(asyncResp);
AppaRao Pulia6349912019-10-18 17:16:08 +05302053#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
2054 getProvisioningStatus(asyncResp);
2055#endif
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002056 }
2057
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002058 void doPatch(crow::Response& res, const crow::Request& req,
Ed Tanouscb13a392020-07-25 19:02:03 +00002059 const std::vector<std::string>&) override
Ed Tanous1abe55e2018-09-05 08:30:59 -07002060 {
Santosh Puranikcde19e52019-02-20 00:10:56 +05302061 std::optional<std::string> indicatorLed;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302062 std::optional<nlohmann::json> bootProps;
Yong Lic45f0082019-10-10 14:19:01 +08002063 std::optional<nlohmann::json> wdtTimerProps;
Gunnar Mills98e386e2020-10-30 14:58:09 -05002064 std::optional<std::string> assetTag;
George Liuc6a620f2020-04-10 17:18:11 +08002065 std::optional<std::string> powerRestorePolicy;
Santosh Puranik41352c22019-07-03 05:35:49 -05002066 auto asyncResp = std::make_shared<AsyncResp>(res);
2067
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07002068 if (!json_util::readJson(req, res, "IndicatorLED", indicatorLed, "Boot",
George Liuc6a620f2020-04-10 17:18:11 +08002069 bootProps, "WatchdogTimer", wdtTimerProps,
Gunnar Mills98e386e2020-10-30 14:58:09 -05002070 "PowerRestorePolicy", powerRestorePolicy,
2071 "AssetTag", assetTag))
Ed Tanous66173382018-08-15 18:20:59 -07002072 {
Ed Tanous9712f8a2018-09-21 13:38:49 -07002073 return;
2074 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302075
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07002076 res.result(boost::beast::http::status::no_content);
Yong Lic45f0082019-10-10 14:19:01 +08002077
Gunnar Mills98e386e2020-10-30 14:58:09 -05002078 if (assetTag)
2079 {
2080 setAssetTag(asyncResp, *assetTag);
2081 }
2082
Yong Lic45f0082019-10-10 14:19:01 +08002083 if (wdtTimerProps)
2084 {
2085 std::optional<bool> wdtEnable;
2086 std::optional<std::string> wdtTimeOutAction;
2087
2088 if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
2089 "FunctionEnabled", wdtEnable,
2090 "TimeoutAction", wdtTimeOutAction))
2091 {
2092 return;
2093 }
Ed Tanousf23b7292020-10-15 09:41:17 -07002094 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
Yong Lic45f0082019-10-10 14:19:01 +08002095 }
2096
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302097 if (bootProps)
2098 {
2099 std::optional<std::string> bootSource;
2100 std::optional<std::string> bootEnable;
Gunnar Mills69f35302020-05-17 16:06:31 -05002101 std::optional<std::string> automaticRetryConfig;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302102
Gunnar Mills69f35302020-05-17 16:06:31 -05002103 if (!json_util::readJson(
2104 *bootProps, asyncResp->res, "BootSourceOverrideTarget",
2105 bootSource, "BootSourceOverrideEnabled", bootEnable,
2106 "AutomaticRetryConfig", automaticRetryConfig))
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302107 {
2108 return;
2109 }
Gunnar Mills69f35302020-05-17 16:06:31 -05002110 if (bootSource || bootEnable)
2111 {
2112 setBootSourceProperties(asyncResp, std::move(bootSource),
2113 std::move(bootEnable));
2114 }
2115 if (automaticRetryConfig)
2116 {
Ed Tanousf23b7292020-10-15 09:41:17 -07002117 setAutomaticRetry(asyncResp, *automaticRetryConfig);
Gunnar Mills69f35302020-05-17 16:06:31 -05002118 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302119 }
Johnathan Mantey265c1602019-08-08 11:02:51 -07002120
Ed Tanous9712f8a2018-09-21 13:38:49 -07002121 if (indicatorLed)
2122 {
Ed Tanousf23b7292020-10-15 09:41:17 -07002123 setIndicatorLedState(asyncResp, *indicatorLed);
Ed Tanous1abe55e2018-09-05 08:30:59 -07002124 }
George Liuc6a620f2020-04-10 17:18:11 +08002125
2126 if (powerRestorePolicy)
2127 {
2128 setPowerRestorePolicy(asyncResp, std::move(*powerRestorePolicy));
2129 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002130 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002131};
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302132
2133/**
2134 * SystemResetActionInfo derived class for delivering Computer Systems
2135 * ResetType AllowableValues using ResetInfo schema.
2136 */
2137class SystemResetActionInfo : public Node
2138{
2139 public:
2140 /*
2141 * Default Constructor
2142 */
Ed Tanous52cc1122020-07-18 13:51:21 -07002143 SystemResetActionInfo(App& app) :
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302144 Node(app, "/redfish/v1/Systems/system/ResetActionInfo/")
2145 {
2146 entityPrivileges = {
2147 {boost::beast::http::verb::get, {{"Login"}}},
2148 {boost::beast::http::verb::head, {{"Login"}}},
2149 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
2150 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
2151 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
2152 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
2153 }
2154
2155 private:
2156 /**
2157 * Functions triggers appropriate requests on DBus
2158 */
Ed Tanouscb13a392020-07-25 19:02:03 +00002159 void doGet(crow::Response& res, const crow::Request&,
2160 const std::vector<std::string>&) override
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05302161 {
2162 res.jsonValue = {
2163 {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
2164 {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
2165 {"Name", "Reset Action Info"},
2166 {"Id", "ResetActionInfo"},
2167 {"Parameters",
2168 {{{"Name", "ResetType"},
2169 {"Required", true},
2170 {"DataType", "String"},
2171 {"AllowableValues",
2172 {"On", "ForceOff", "ForceOn", "ForceRestart", "GracefulRestart",
2173 "GracefulShutdown", "PowerCycle", "Nmi"}}}}}};
2174 res.end();
2175 }
2176};
Ed Tanous1abe55e2018-09-05 08:30:59 -07002177} // namespace redfish