blob: c092379b727a983e3bb57fa15db9c7fd0901d7d1 [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 Kumari57e8c9b2019-04-15 01:09:36 -050031/*
32 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
33 *
34 * @param[in] aResp Shared pointer for completing asynchronous calls
35 * @param[in] cpuPresenceState CPU present or not
36 *
37 * @return None.
38 */
39void modifyCpuPresenceState(std::shared_ptr<AsyncResp> aResp,
40 const std::variant<bool> &cpuPresenceState)
41{
42 const bool *isCpuPresent = std::get_if<bool>(&cpuPresenceState);
43
44 if (isCpuPresent == nullptr)
45 {
46 messages::internalError(aResp->res);
47 return;
48 }
49 BMCWEB_LOG_DEBUG << "Cpu Present:" << *isCpuPresent;
50
51 nlohmann::json &procCount =
52 aResp->res.jsonValue["ProcessorSummary"]["Count"];
53 if (*isCpuPresent == true)
54 {
55 procCount = procCount.get<int>() + 1;
56 }
57 aResp->res.jsonValue["ProcessorSummary"]["Count"] = procCount;
58}
59
60/*
61 * @brief Update "ProcessorSummary" "Status" "State" based on
62 * CPU Functional State
63 *
64 * @param[in] aResp Shared pointer for completing asynchronous calls
65 * @param[in] cpuFunctionalState is CPU functional true/false
66 *
67 * @return None.
68 */
69void modifyCpuFunctionalState(std::shared_ptr<AsyncResp> aResp,
70 const std::variant<bool> &cpuFunctionalState)
71{
72 const bool *isCpuFunctional = std::get_if<bool>(&cpuFunctionalState);
73
74 if (isCpuFunctional == nullptr)
75 {
76 messages::internalError(aResp->res);
77 return;
78 }
79 BMCWEB_LOG_DEBUG << "Cpu Functional:" << *isCpuFunctional;
80
81 nlohmann::json &prevProcState =
82 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
83
84 // Set it as Enabled if atleast one CPU is functional
85 // Update STATE only if previous State was Non_Functional and current CPU is
86 // Functional.
87 if (prevProcState == "Disabled")
88 {
89 if (*isCpuFunctional == true)
90 {
91 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
92 "Enabled";
93 }
94 }
95}
96
97/*
Ed Tanous6c34de42018-08-29 13:37:36 -070098 * @brief Retrieves computer system properties over dbus
99 *
100 * @param[in] aResp Shared pointer for completing asynchronous calls
101 * @param[in] name Computer system name from request
102 *
103 * @return None.
104 */
Ed Tanous029573d2019-02-01 10:57:49 -0800105void getComputerSystem(std::shared_ptr<AsyncResp> aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700106{
Ed Tanous6c34de42018-08-29 13:37:36 -0700107 BMCWEB_LOG_DEBUG << "Get available system components.";
108 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800109 [aResp](
Ed Tanous6c34de42018-08-29 13:37:36 -0700110 const boost::system::error_code ec,
111 const std::vector<std::pair<
112 std::string,
113 std::vector<std::pair<std::string, std::vector<std::string>>>>>
114 &subtree) {
115 if (ec)
116 {
117 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700118 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700119 return;
120 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700121 // Iterate over all retrieved ObjectPaths.
122 for (const std::pair<std::string,
123 std::vector<std::pair<
124 std::string, std::vector<std::string>>>>
125 &object : subtree)
126 {
127 const std::string &path = object.first;
128 BMCWEB_LOG_DEBUG << "Got path: " << path;
129 const std::vector<
130 std::pair<std::string, std::vector<std::string>>>
131 &connectionNames = object.second;
132 if (connectionNames.size() < 1)
133 {
134 continue;
135 }
Ed Tanous029573d2019-02-01 10:57:49 -0800136
137 // This is not system, so check if it's cpu, dimm, UUID or
138 // BiosVer
139 for (const auto &connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700140 {
Ed Tanous029573d2019-02-01 10:57:49 -0800141 for (const auto &interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700142 {
Ed Tanous029573d2019-02-01 10:57:49 -0800143 if (interfaceName ==
144 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700145 {
Ed Tanous029573d2019-02-01 10:57:49 -0800146 BMCWEB_LOG_DEBUG
147 << "Found Dimm, now get its properties.";
148 crow::connections::systemBus->async_method_call(
149 [aResp](const boost::system::error_code ec,
Ed Tanous6c34de42018-08-29 13:37:36 -0700150 const std::vector<
151 std::pair<std::string, VariantType>>
152 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800153 if (ec)
154 {
155 BMCWEB_LOG_ERROR
156 << "DBUS response error " << ec;
157 messages::internalError(aResp->res);
158 return;
159 }
160 BMCWEB_LOG_DEBUG << "Got "
161 << properties.size()
162 << "Dimm properties.";
163 for (const std::pair<std::string,
164 VariantType>
165 &property : properties)
166 {
167 if (property.first == "MemorySizeInKb")
Ed Tanous6c34de42018-08-29 13:37:36 -0700168 {
Ed Tanous029573d2019-02-01 10:57:49 -0800169 const uint64_t *value =
170 sdbusplus::message::variant_ns::
171 get_if<uint64_t>(
172 &property.second);
173 if (value != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700174 {
Ed Tanous029573d2019-02-01 10:57:49 -0800175 aResp->res.jsonValue
176 ["TotalSystemMemoryGi"
177 "B"] +=
178 *value / (1024 * 1024);
179 aResp->res
180 .jsonValue["MemorySummary"]
181 ["Status"]
182 ["State"] =
183 "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700184 }
185 }
Ed Tanous029573d2019-02-01 10:57:49 -0800186 }
187 },
188 connection.first, path,
189 "org.freedesktop.DBus.Properties", "GetAll",
190 "xyz.openbmc_project.Inventory.Item.Dimm");
191 }
192 else if (interfaceName ==
193 "xyz.openbmc_project.Inventory.Item.Cpu")
194 {
195 BMCWEB_LOG_DEBUG
196 << "Found Cpu, now get its properties.";
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500197
Ed Tanous029573d2019-02-01 10:57:49 -0800198 crow::connections::systemBus->async_method_call(
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500199 [aResp, service{connection.first},
200 path(std::move(path))](
201 const boost::system::error_code ec,
202 const std::vector<
203 std::pair<std::string, VariantType>>
204 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800205 if (ec)
206 {
207 BMCWEB_LOG_ERROR
208 << "DBUS response error " << ec;
209 messages::internalError(aResp->res);
210 return;
211 }
212 BMCWEB_LOG_DEBUG << "Got "
213 << properties.size()
214 << "Cpu properties.";
Ed Tanous04a258f2018-10-15 08:00:41 -0700215
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500216 if (properties.size() > 0)
217 {
218 for (const auto &property : properties)
219 {
220 if (property.first ==
221 "ProcessorFamily")
222 {
223 const std::string *value =
224 sdbusplus::message::
225 variant_ns::get_if<
226 std::string>(
227 &property.second);
228 if (value != nullptr)
229 {
230 nlohmann::json
231 &procSummary =
232 aResp->res.jsonValue
233 ["ProcessorSumm"
234 "ary"];
235 nlohmann::json &procCount =
236 procSummary["Count"];
237 procCount =
238 procCount.get<int>() +
239 1;
240 procSummary["Status"]
241 ["State"] =
242 "Enabled";
243 procSummary["Model"] =
244 *value;
245 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700246 }
247 }
Ed Tanous029573d2019-02-01 10:57:49 -0800248 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500249 else
250 {
251 auto getCpuPresenceState =
252 [aResp](
253 const boost::system::error_code
254 ec,
255 const std::variant<bool>
256 &cpuPresenceCheck) {
257 if (ec)
258 {
259 BMCWEB_LOG_ERROR
260 << "DBUS response "
261 "error "
262 << ec;
263 return;
264 }
265 modifyCpuPresenceState(
266 aResp, cpuPresenceCheck);
267 };
268
269 auto getCpuFunctionalState =
270 [aResp](
271 const boost::system::error_code
272 ec,
273 const std::variant<bool>
274 &cpuFunctionalCheck) {
275 if (ec)
276 {
277 BMCWEB_LOG_ERROR
278 << "DBUS response "
279 "error "
280 << ec;
281 return;
282 }
283 modifyCpuFunctionalState(
284 aResp, cpuFunctionalCheck);
285 };
286 // Get the Presence of CPU
287 crow::connections::systemBus
288 ->async_method_call(
289 std::move(getCpuPresenceState),
290 service, path,
291 "org.freedesktop.DBus."
292 "Properties",
293 "Get",
294 "xyz.openbmc_project.Inventory."
295 "Item",
296 "Present");
297
298 // Get the Functional State
299 crow::connections::systemBus
300 ->async_method_call(
301 std::move(
302 getCpuFunctionalState),
303 service, path,
304 "org.freedesktop.DBus."
305 "Properties",
306 "Get",
307 "xyz.openbmc_project.State."
308 "Decorator."
309 "OperationalStatus",
310 "Functional");
311
312 // Get the MODEL from
313 // xyz.openbmc_project.Inventory.Decorator.Asset
314 // support it later as Model is Empty
315 // currently.
316 }
Ed Tanous029573d2019-02-01 10:57:49 -0800317 },
318 connection.first, path,
319 "org.freedesktop.DBus.Properties", "GetAll",
320 "xyz.openbmc_project.Inventory.Item.Cpu");
321 }
322 else if (interfaceName ==
323 "xyz.openbmc_project.Common.UUID")
324 {
325 BMCWEB_LOG_DEBUG
326 << "Found UUID, now get its properties.";
327 crow::connections::systemBus->async_method_call(
328 [aResp](const boost::system::error_code ec,
Ed Tanous6c34de42018-08-29 13:37:36 -0700329 const std::vector<
330 std::pair<std::string, VariantType>>
331 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800332 if (ec)
333 {
334 BMCWEB_LOG_DEBUG
335 << "DBUS response error " << ec;
336 messages::internalError(aResp->res);
337 return;
338 }
339 BMCWEB_LOG_DEBUG << "Got "
340 << properties.size()
341 << "UUID properties.";
342 for (const std::pair<std::string,
343 VariantType>
344 &property : properties)
345 {
Ed Tanous029573d2019-02-01 10:57:49 -0800346 if (property.first == "UUID")
347 {
348 const std::string *value =
349 sdbusplus::message::variant_ns::
350 get_if<std::string>(
351 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700352
Ed Tanous029573d2019-02-01 10:57:49 -0800353 if (value != nullptr)
354 {
355 std::string valueStr = *value;
356 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700357 {
Ed Tanous029573d2019-02-01 10:57:49 -0800358 valueStr.insert(8, 1, '-');
359 valueStr.insert(13, 1, '-');
360 valueStr.insert(18, 1, '-');
361 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700362 }
Ed Tanous029573d2019-02-01 10:57:49 -0800363 BMCWEB_LOG_DEBUG << "UUID = "
364 << valueStr;
365 aResp->res.jsonValue["UUID"] =
366 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700367 }
368 }
Ed Tanous029573d2019-02-01 10:57:49 -0800369 }
370 },
371 connection.first, path,
372 "org.freedesktop.DBus.Properties", "GetAll",
373 "xyz.openbmc_project.Common.UUID");
374 }
375 else if (interfaceName ==
376 "xyz.openbmc_project.Inventory.Item.System")
377 {
378 crow::connections::systemBus->async_method_call(
379 [aResp](const boost::system::error_code ec,
380 const std::vector<
381 std::pair<std::string, VariantType>>
382 &propertiesList) {
383 if (ec)
384 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700385 // doesn't have to include this
386 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800387 return;
388 }
389 BMCWEB_LOG_DEBUG << "Got "
390 << propertiesList.size()
391 << "properties for system";
392 for (const std::pair<std::string,
393 VariantType>
394 &property : propertiesList)
395 {
beccabroekfc5afcf2019-03-05 14:35:15 -0600396 const std::string &propertyName =
397 property.first;
398 if ((propertyName == "PartNumber") ||
399 (propertyName == "SerialNumber") ||
400 (propertyName == "Manufacturer") ||
401 (propertyName == "Model"))
Ed Tanous029573d2019-02-01 10:57:49 -0800402 {
beccabroekfc5afcf2019-03-05 14:35:15 -0600403 const std::string *value =
404 std::get_if<std::string>(
405 &property.second);
406 if (value != nullptr)
407 {
408 aResp->res
409 .jsonValue[propertyName] =
410 *value;
411 }
Ed Tanous029573d2019-02-01 10:57:49 -0800412 }
413 }
414 aResp->res.jsonValue["Name"] = "system";
415 aResp->res.jsonValue["Id"] =
416 aResp->res.jsonValue["SerialNumber"];
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600417 // Grab the bios version
418 fw_util::getActiveFwVersion(
419 aResp, fw_util::biosPurpose,
420 "BiosVersion");
Ed Tanous029573d2019-02-01 10:57:49 -0800421 },
422 connection.first, path,
423 "org.freedesktop.DBus.Properties", "GetAll",
424 "xyz.openbmc_project.Inventory.Decorator."
425 "Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700426
427 crow::connections::systemBus->async_method_call(
428 [aResp](
429 const boost::system::error_code ec,
430 const std::variant<std::string> &property) {
431 if (ec)
432 {
433 // doesn't have to include this
434 // interface
435 return;
436 }
437
438 const std::string *value =
439 std::get_if<std::string>(&property);
440 if (value != nullptr)
441 {
442 aResp->res.jsonValue["AssetTag"] =
443 *value;
444 }
445 },
446 connection.first, path,
447 "org.freedesktop.DBus.Properties", "Get",
448 "xyz.openbmc_project.Inventory.Decorator."
449 "AssetTag",
450 "AssetTag");
Ed Tanous6c34de42018-08-29 13:37:36 -0700451 }
452 }
453 }
454 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700455 },
456 "xyz.openbmc_project.ObjectMapper",
457 "/xyz/openbmc_project/object_mapper",
458 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700459 "/xyz/openbmc_project/inventory", int32_t(0),
460 std::array<const char *, 5>{
461 "xyz.openbmc_project.Inventory.Decorator.Asset",
462 "xyz.openbmc_project.Inventory.Item.Cpu",
463 "xyz.openbmc_project.Inventory.Item.Dimm",
464 "xyz.openbmc_project.Inventory.Item.System",
465 "xyz.openbmc_project.Common.UUID",
466 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700467}
468
469/**
470 * @brief Retrieves identify led group properties over dbus
471 *
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530472 * @param[in] aResp Shared pointer for generating response message.
Ed Tanous6c34de42018-08-29 13:37:36 -0700473 * @param[in] callback Callback for process retrieved data.
474 *
475 * @return None.
476 */
477template <typename CallbackFunc>
478void getLedGroupIdentify(std::shared_ptr<AsyncResp> aResp,
479 CallbackFunc &&callback)
480{
481 BMCWEB_LOG_DEBUG << "Get led groups";
482 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800483 [aResp,
Ed Tanous66173382018-08-15 18:20:59 -0700484 callback{std::move(callback)}](const boost::system::error_code &ec,
485 const ManagedObjectsType &resp) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700486 if (ec)
487 {
488 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700489 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700490 return;
491 }
492 BMCWEB_LOG_DEBUG << "Got " << resp.size() << "led group objects.";
493 for (const auto &objPath : resp)
494 {
495 const std::string &path = objPath.first;
496 if (path.rfind("enclosure_identify") != std::string::npos)
497 {
498 for (const auto &interface : objPath.second)
499 {
500 if (interface.first == "xyz.openbmc_project.Led.Group")
501 {
502 for (const auto &property : interface.second)
503 {
504 if (property.first == "Asserted")
505 {
506 const bool *asserted =
Ed Tanousabf2add2019-01-22 16:40:12 -0800507 std::get_if<bool>(&property.second);
Ed Tanous6c34de42018-08-29 13:37:36 -0700508 if (nullptr != asserted)
509 {
510 callback(*asserted, aResp);
511 }
512 else
513 {
514 callback(false, aResp);
515 }
516 }
517 }
518 }
519 }
520 }
521 }
522 },
523 "xyz.openbmc_project.LED.GroupManager",
524 "/xyz/openbmc_project/led/groups", "org.freedesktop.DBus.ObjectManager",
525 "GetManagedObjects");
526}
527
528template <typename CallbackFunc>
529void getLedIdentify(std::shared_ptr<AsyncResp> aResp, CallbackFunc &&callback)
530{
531 BMCWEB_LOG_DEBUG << "Get identify led properties";
532 crow::connections::systemBus->async_method_call(
Ed Tanous66173382018-08-15 18:20:59 -0700533 [aResp,
534 callback{std::move(callback)}](const boost::system::error_code ec,
535 const PropertiesType &properties) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700536 if (ec)
537 {
538 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700539 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700540 return;
541 }
542 BMCWEB_LOG_DEBUG << "Got " << properties.size()
543 << "led properties.";
544 std::string output;
545 for (const auto &property : properties)
546 {
547 if (property.first == "State")
548 {
549 const std::string *s =
Ed Tanousabf2add2019-01-22 16:40:12 -0800550 std::get_if<std::string>(&property.second);
Ed Tanous6c34de42018-08-29 13:37:36 -0700551 if (nullptr != s)
552 {
553 BMCWEB_LOG_DEBUG << "Identify Led State: " << *s;
554 const auto pos = s->rfind('.');
555 if (pos != std::string::npos)
556 {
557 auto led = s->substr(pos + 1);
558 for (const std::pair<const char *, const char *>
559 &p :
560 std::array<
561 std::pair<const char *, const char *>, 3>{
562 {{"On", "Lit"},
563 {"Blink", "Blinking"},
564 {"Off", "Off"}}})
565 {
566 if (led == p.first)
567 {
568 output = p.second;
569 }
570 }
571 }
572 }
573 }
574 }
575 callback(output, aResp);
576 },
577 "xyz.openbmc_project.LED.Controller.identify",
578 "/xyz/openbmc_project/led/physical/identify",
579 "org.freedesktop.DBus.Properties", "GetAll",
580 "xyz.openbmc_project.Led.Physical");
581}
Ed Tanous6c34de42018-08-29 13:37:36 -0700582/**
583 * @brief Retrieves host state properties over dbus
584 *
585 * @param[in] aResp Shared pointer for completing asynchronous calls.
586 *
587 * @return None.
588 */
589void getHostState(std::shared_ptr<AsyncResp> aResp)
590{
591 BMCWEB_LOG_DEBUG << "Get host information.";
592 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800593 [aResp](const boost::system::error_code ec,
594 const std::variant<std::string> &hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700595 if (ec)
596 {
597 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700598 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700599 return;
600 }
Ed Tanous66173382018-08-15 18:20:59 -0700601
Ed Tanousabf2add2019-01-22 16:40:12 -0800602 const std::string *s = std::get_if<std::string>(&hostState);
Ed Tanous66173382018-08-15 18:20:59 -0700603 BMCWEB_LOG_DEBUG << "Host state: " << *s;
604 if (s != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700605 {
Ed Tanous66173382018-08-15 18:20:59 -0700606 // Verify Host State
Andrew Geissler94732662019-01-08 19:32:16 -0800607 if (*s == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700608 {
Ed Tanous66173382018-08-15 18:20:59 -0700609 aResp->res.jsonValue["PowerState"] = "On";
610 aResp->res.jsonValue["Status"]["State"] = "Enabled";
611 }
612 else
613 {
614 aResp->res.jsonValue["PowerState"] = "Off";
615 aResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700616 }
617 }
618 },
619 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Ed Tanous66173382018-08-15 18:20:59 -0700620 "org.freedesktop.DBus.Properties", "Get",
621 "xyz.openbmc_project.State.Host", "CurrentHostState");
Ed Tanous6c34de42018-08-29 13:37:36 -0700622}
623
624/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530625 * @brief Traslates boot source DBUS property value to redfish.
626 *
627 * @param[in] dbusSource The boot source in DBUS speak.
628 *
629 * @return Returns as a string, the boot source in Redfish terms. If translation
630 * cannot be done, returns an empty string.
631 */
632static std::string dbusToRfBootSource(const std::string &dbusSource)
633{
634 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
635 {
636 return "None";
637 }
638 else if (dbusSource ==
639 "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
640 {
641 return "Hdd";
642 }
643 else if (dbusSource ==
Santosh Puranika71dc0b2019-05-23 20:10:49 +0530644 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530645 {
646 return "Cd";
647 }
648 else if (dbusSource ==
649 "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
650 {
651 return "Pxe";
652 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700653 else if (dbusSource ==
654 "xyz.openbmc_project.Control.Boot.Source.Sources.Removable")
655 {
656 return "Usb";
657 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530658 else
659 {
660 return "";
661 }
662}
663
664/**
665 * @brief Traslates boot mode DBUS property value to redfish.
666 *
667 * @param[in] dbusMode The boot mode in DBUS speak.
668 *
669 * @return Returns as a string, the boot mode in Redfish terms. If translation
670 * cannot be done, returns an empty string.
671 */
672static std::string dbusToRfBootMode(const std::string &dbusMode)
673{
674 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
675 {
676 return "None";
677 }
678 else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
679 {
680 return "Diags";
681 }
682 else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
683 {
684 return "BiosSetup";
685 }
686 else
687 {
688 return "";
689 }
690}
691
692/**
693 * @brief Traslates boot source from Redfish to DBUS property value.
694 *
695 * @param[in] rfSource The boot source in Redfish.
696 *
697 * @return Returns as a string, the boot source as expected by DBUS.
698 * If translation cannot be done, returns an empty string.
699 */
700static std::string rfToDbusBootSource(const std::string &rfSource)
701{
702 if (rfSource == "None")
703 {
704 return "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
705 }
706 else if (rfSource == "Hdd")
707 {
708 return "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
709 }
710 else if (rfSource == "Cd")
711 {
Santosh Puranika71dc0b2019-05-23 20:10:49 +0530712 return "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530713 }
714 else if (rfSource == "Pxe")
715 {
716 return "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
717 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700718 else if (rfSource == "Usb")
719 {
720 return "xyz.openbmc_project.Control.Boot.Source.Sources.Removable";
721 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530722 else
723 {
724 return "";
725 }
726}
727
728/**
729 * @brief Traslates boot mode from Redfish to DBUS property value.
730 *
731 * @param[in] rfMode The boot mode in Redfish.
732 *
733 * @return Returns as a string, the boot mode as expected by DBUS.
734 * If translation cannot be done, returns an empty string.
735 */
736static std::string rfToDbusBootMode(const std::string &rfMode)
737{
738 if (rfMode == "None")
739 {
740 return "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
741 }
742 else if (rfMode == "Diags")
743 {
744 return "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
745 }
746 else if (rfMode == "BiosSetup")
747 {
748 return "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
749 }
750 else
751 {
752 return "";
753 }
754}
755
756/**
757 * @brief Retrieves boot mode over DBUS and fills out the response
758 *
759 * @param[in] aResp Shared pointer for generating response message.
760 * @param[in] bootDbusObj The dbus object to query for boot properties.
761 *
762 * @return None.
763 */
764static void getBootMode(std::shared_ptr<AsyncResp> aResp,
765 std::string bootDbusObj)
766{
767 crow::connections::systemBus->async_method_call(
768 [aResp](const boost::system::error_code ec,
769 const std::variant<std::string> &bootMode) {
770 if (ec)
771 {
772 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
773 messages::internalError(aResp->res);
774 return;
775 }
776
777 const std::string *bootModeStr =
778 std::get_if<std::string>(&bootMode);
779
780 if (!bootModeStr)
781 {
782 messages::internalError(aResp->res);
783 return;
784 }
785
786 BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
787
788 // TODO (Santosh): Do we need to support override mode?
789 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = "Legacy";
790 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
791 "AllowableValues"] = {
792 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup"};
793
794 if (*bootModeStr !=
795 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
796 {
797 auto rfMode = dbusToRfBootMode(*bootModeStr);
798 if (!rfMode.empty())
799 {
800 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
801 rfMode;
802 }
803 }
804
805 // If the BootSourceOverrideTarget is still "None" at the end,
806 // reset the BootSourceOverrideEnabled to indicate that
807 // overrides are disabled
808 if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] ==
809 "None")
810 {
811 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
812 "Disabled";
813 }
814 },
815 "xyz.openbmc_project.Settings", bootDbusObj,
816 "org.freedesktop.DBus.Properties", "Get",
817 "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
818}
819
820/**
821 * @brief Retrieves boot source over DBUS
822 *
823 * @param[in] aResp Shared pointer for generating response message.
824 * @param[in] oneTimeEnable Boolean to indicate boot properties are one-time.
825 *
826 * @return None.
827 */
828static void getBootSource(std::shared_ptr<AsyncResp> aResp, bool oneTimeEnabled)
829{
830 std::string bootDbusObj =
831 oneTimeEnabled ? "/xyz/openbmc_project/control/host0/boot/one_time"
832 : "/xyz/openbmc_project/control/host0/boot";
833
834 BMCWEB_LOG_DEBUG << "Is one time: " << oneTimeEnabled;
835 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
836 (oneTimeEnabled) ? "Once" : "Continuous";
837
838 crow::connections::systemBus->async_method_call(
839 [aResp, bootDbusObj](const boost::system::error_code ec,
840 const std::variant<std::string> &bootSource) {
841 if (ec)
842 {
843 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
844 messages::internalError(aResp->res);
845 return;
846 }
847
848 const std::string *bootSourceStr =
849 std::get_if<std::string>(&bootSource);
850
851 if (!bootSourceStr)
852 {
853 messages::internalError(aResp->res);
854 return;
855 }
856 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
857
858 auto rfSource = dbusToRfBootSource(*bootSourceStr);
859 if (!rfSource.empty())
860 {
861 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
862 rfSource;
863 }
864 },
865 "xyz.openbmc_project.Settings", bootDbusObj,
866 "org.freedesktop.DBus.Properties", "Get",
867 "xyz.openbmc_project.Control.Boot.Source", "BootSource");
868 getBootMode(std::move(aResp), std::move(bootDbusObj));
869}
870
871/**
872 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
873 * get boot source and boot mode.
874 *
875 * @param[in] aResp Shared pointer for generating response message.
876 *
877 * @return None.
878 */
879static void getBootProperties(std::shared_ptr<AsyncResp> aResp)
880{
881 BMCWEB_LOG_DEBUG << "Get boot information.";
882
883 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800884 [aResp](const boost::system::error_code ec,
885 const sdbusplus::message::variant<bool> &oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530886 if (ec)
887 {
888 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
James Feist2a833c72019-07-19 10:17:13 -0700889 // not an error, don't have to have the interface
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530890 return;
891 }
892
893 const bool *oneTimePtr = std::get_if<bool>(&oneTime);
894
895 if (!oneTimePtr)
896 {
897 messages::internalError(aResp->res);
898 return;
899 }
900 getBootSource(aResp, *oneTimePtr);
901 },
902 "xyz.openbmc_project.Settings",
903 "/xyz/openbmc_project/control/host0/boot/one_time",
904 "org.freedesktop.DBus.Properties", "Get",
905 "xyz.openbmc_project.Object.Enable", "Enabled");
906}
907
908/**
909 * @brief Sets boot properties into DBUS object(s).
910 *
911 * @param[in] aResp Shared pointer for generating response message.
912 * @param[in] oneTimeEnabled Is "one-time" setting already enabled.
913 * @param[in] bootSource The boot source to set.
914 * @param[in] bootEnable The source override "enable" to set.
915 *
916 * @return None.
917 */
918static void setBootModeOrSource(std::shared_ptr<AsyncResp> aResp,
919 bool oneTimeEnabled,
920 std::optional<std::string> bootSource,
921 std::optional<std::string> bootEnable)
922{
923 if (bootEnable && (bootEnable != "Once") && (bootEnable != "Continuous") &&
924 (bootEnable != "Disabled"))
925 {
926 BMCWEB_LOG_DEBUG << "Unsupported value for BootSourceOverrideEnabled: "
927 << *bootEnable;
928 messages::propertyValueNotInList(aResp->res, *bootEnable,
929 "BootSourceOverrideEnabled");
930 return;
931 }
932
933 bool oneTimeSetting = oneTimeEnabled;
934 // Validate incoming parameters
935 if (bootEnable)
936 {
937 if (*bootEnable == "Once")
938 {
939 oneTimeSetting = true;
940 }
941 else if (*bootEnable == "Continuous")
942 {
943 oneTimeSetting = false;
944 }
945 else if (*bootEnable == "Disabled")
946 {
947 oneTimeSetting = false;
948 }
949 else
950 {
951
952 BMCWEB_LOG_DEBUG << "Unsupported value for "
953 "BootSourceOverrideEnabled: "
954 << *bootEnable;
955 messages::propertyValueNotInList(aResp->res, *bootEnable,
956 "BootSourceOverrideEnabled");
957 return;
958 }
959 }
960 std::string bootSourceStr;
961 std::string bootModeStr;
962 if (bootSource)
963 {
964 bootSourceStr = rfToDbusBootSource(*bootSource);
965 bootModeStr = rfToDbusBootMode(*bootSource);
966
967 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
968 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
969
970 if (bootSourceStr.empty() && bootModeStr.empty())
971 {
972 BMCWEB_LOG_DEBUG << "Invalid property value for "
973 "BootSourceOverrideTarget: "
974 << *bootSource;
975 messages::propertyValueNotInList(aResp->res, *bootSource,
976 "BootSourceTargetOverride");
977 return;
978 }
979 }
980 const char *bootObj =
981 oneTimeSetting ? "/xyz/openbmc_project/control/host0/boot/one_time"
982 : "/xyz/openbmc_project/control/host0/boot";
983 // Figure out what properties to set
984 if (bootEnable && (*bootEnable == "Disabled"))
985 {
986 BMCWEB_LOG_DEBUG << "Boot source override will be disabled";
987 // Request to only turn OFF/ON enabled, if turning enabled OFF, need
988 // to reset the source and mode too. If turning it ON, we only need
989 // to set the enabled property
990 bootSourceStr =
991 "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
992 bootModeStr = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
993 }
994 else if (bootSource)
995 {
996 // Source target specified
997 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
998 // Figure out which DBUS interface and property to use
999 bootSourceStr = rfToDbusBootSource(*bootSource);
1000 bootModeStr = rfToDbusBootMode(*bootSource);
1001
1002 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1003 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
1004
1005 if (bootSourceStr.empty() && bootModeStr.empty())
1006 {
1007 BMCWEB_LOG_DEBUG << "Invalid property value for "
1008 "BootSourceOverrideTarget: "
1009 << *bootSource;
1010 messages::propertyValueNotInList(aResp->res, *bootSource,
1011 "BootSourceTargetOverride");
1012 return;
1013 }
1014
1015 if (!bootSourceStr.empty())
1016 {
1017 // If setting to anything other than default, also reset boot
1018 // mode property
1019 if (bootSourceStr !=
1020 "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
1021 {
1022 bootModeStr =
1023 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
1024 }
1025 }
1026 else // if (!bootModeStr.empty())
1027 {
1028 // If setting to anything other than default, also reset boot
1029 // source property
1030 if (bootModeStr !=
1031 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
1032 {
1033 bootSourceStr =
1034 "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
1035 }
1036 }
1037 }
1038 if (!bootSourceStr.empty())
1039 {
1040 crow::connections::systemBus->async_method_call(
1041 [aResp](const boost::system::error_code ec) {
1042 if (ec)
1043 {
1044 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1045 messages::internalError(aResp->res);
1046 return;
1047 }
1048 BMCWEB_LOG_DEBUG << "Boot source update done.";
1049 },
1050 "xyz.openbmc_project.Settings", bootObj,
1051 "org.freedesktop.DBus.Properties", "Set",
1052 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1053 std::variant<std::string>(bootSourceStr));
1054 }
1055 if (!bootModeStr.empty())
1056 {
1057 crow::connections::systemBus->async_method_call(
1058 [aResp](const boost::system::error_code ec) {
1059 if (ec)
1060 {
1061 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1062 messages::internalError(aResp->res);
1063 return;
1064 }
1065 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1066 },
1067 "xyz.openbmc_project.Settings", bootObj,
1068 "org.freedesktop.DBus.Properties", "Set",
1069 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1070 std::variant<std::string>(bootModeStr));
1071 }
1072 crow::connections::systemBus->async_method_call(
1073 [aResp{std::move(aResp)}](const boost::system::error_code ec) {
1074 if (ec)
1075 {
1076 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1077 messages::internalError(aResp->res);
1078 return;
1079 }
1080 BMCWEB_LOG_DEBUG << "Boot enable update done.";
1081 },
1082 "xyz.openbmc_project.Settings",
1083 "/xyz/openbmc_project/control/host0/boot/one_time",
1084 "org.freedesktop.DBus.Properties", "Set",
1085 "xyz.openbmc_project.Object.Enable", "Enabled",
1086 std::variant<bool>(oneTimeSetting));
1087}
1088
1089/**
1090 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
1091 * set boot source/boot mode properties.
1092 *
1093 * @param[in] aResp Shared pointer for generating response message.
1094 * @param[in] bootSource The boot source from incoming RF request.
1095 * @param[in] bootEnable The boot override enable from incoming RF request.
1096 *
1097 * @return None.
1098 */
1099static void setBootProperties(std::shared_ptr<AsyncResp> aResp,
1100 std::optional<std::string> bootSource,
1101 std::optional<std::string> bootEnable)
1102{
1103 BMCWEB_LOG_DEBUG << "Set boot information.";
1104
1105 crow::connections::systemBus->async_method_call(
1106 [aResp{std::move(aResp)}, bootSource{std::move(bootSource)},
1107 bootEnable{std::move(bootEnable)}](
1108 const boost::system::error_code ec,
1109 const sdbusplus::message::variant<bool> &oneTime) {
1110 if (ec)
1111 {
1112 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1113 messages::internalError(aResp->res);
1114 return;
1115 }
1116
1117 const bool *oneTimePtr = std::get_if<bool>(&oneTime);
1118
1119 if (!oneTimePtr)
1120 {
1121 messages::internalError(aResp->res);
1122 return;
1123 }
1124
1125 BMCWEB_LOG_DEBUG << "Got one time: " << *oneTimePtr;
1126
1127 setBootModeOrSource(aResp, *oneTimePtr, std::move(bootSource),
1128 std::move(bootEnable));
1129 },
1130 "xyz.openbmc_project.Settings",
1131 "/xyz/openbmc_project/control/host0/boot/one_time",
1132 "org.freedesktop.DBus.Properties", "Get",
1133 "xyz.openbmc_project.Object.Enable", "Enabled");
1134}
1135
1136/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001137 * SystemsCollection derived class for delivering ComputerSystems Collection
1138 * Schema
1139 */
Ed Tanous1abe55e2018-09-05 08:30:59 -07001140class SystemsCollection : public Node
1141{
1142 public:
1143 SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/")
1144 {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001145 entityPrivileges = {
1146 {boost::beast::http::verb::get, {{"Login"}}},
1147 {boost::beast::http::verb::head, {{"Login"}}},
1148 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1149 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1150 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1151 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1152 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001153
Ed Tanous1abe55e2018-09-05 08:30:59 -07001154 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -07001155 void doGet(crow::Response &res, const crow::Request &req,
1156 const std::vector<std::string> &params) override
1157 {
Ed Tanous0f74e642018-11-12 15:17:05 -08001158 res.jsonValue["@odata.type"] =
1159 "#ComputerSystemCollection.ComputerSystemCollection";
1160 res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
1161 res.jsonValue["@odata.context"] =
1162 "/redfish/v1/"
1163 "$metadata#ComputerSystemCollection.ComputerSystemCollection";
1164 res.jsonValue["Name"] = "Computer System Collection";
Ed Tanous029573d2019-02-01 10:57:49 -08001165 res.jsonValue["Members"] = {
1166 {{"@odata.id", "/redfish/v1/Systems/system"}}};
1167 res.jsonValue["Members@odata.count"] = 1;
1168 res.end();
Ed Tanous1abe55e2018-09-05 08:30:59 -07001169 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001170};
1171
1172/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07001173 * SystemActionsReset class supports handle POST method for Reset action.
1174 * The class retrieves and sends data directly to D-Bus.
1175 */
1176class SystemActionsReset : public Node
1177{
1178 public:
1179 SystemActionsReset(CrowApp &app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001180 Node(app, "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanouscc340dd2018-08-29 13:43:38 -07001181 {
1182 entityPrivileges = {
1183 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1184 }
1185
1186 private:
1187 /**
1188 * Function handles POST method request.
1189 * Analyzes POST body message before sends Reset request data to D-Bus.
1190 */
1191 void doPost(crow::Response &res, const crow::Request &req,
1192 const std::vector<std::string> &params) override
1193 {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001194 auto asyncResp = std::make_shared<AsyncResp>(res);
1195
1196 std::string resetType;
1197 if (!json_util::readJson(req, res, "ResetType", resetType))
Ed Tanouscc340dd2018-08-29 13:43:38 -07001198 {
1199 return;
1200 }
1201
Jason M. Billsd22c8392019-06-03 13:59:03 -07001202 // Get the command and host vs. chassis
Ed Tanous9712f8a2018-09-21 13:38:49 -07001203 std::string command;
Jason M. Billsd22c8392019-06-03 13:59:03 -07001204 bool hostCommand;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001205 if (resetType == "On")
1206 {
1207 command = "xyz.openbmc_project.State.Host.Transition.On";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001208 hostCommand = true;
1209 }
1210 else if (resetType == "ForceOff")
1211 {
1212 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
1213 hostCommand = false;
1214 }
1215 else if (resetType == "ForceOn")
1216 {
1217 command = "xyz.openbmc_project.State.Host.Transition.On";
1218 hostCommand = true;
1219 }
1220 else if (resetType == "ForceRestart")
1221 {
1222 command = "xyz.openbmc_project.State.Chassis.Transition.Reset";
1223 hostCommand = false;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001224 }
1225 else if (resetType == "GracefulShutdown")
1226 {
1227 command = "xyz.openbmc_project.State.Host.Transition.Off";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001228 hostCommand = true;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001229 }
1230 else if (resetType == "GracefulRestart")
1231 {
1232 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001233 hostCommand = true;
1234 }
1235 else if (resetType == "PowerCycle")
1236 {
1237 command = "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
1238 hostCommand = false;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001239 }
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001240 else if (resetType == "Nmi")
1241 {
1242 doNMI(asyncResp);
1243 return;
1244 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001245 else
1246 {
Jason M. Billsf12894f2018-10-09 12:45:45 -07001247 messages::actionParameterUnknown(res, "Reset", resetType);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001248 return;
1249 }
1250
Jason M. Billsd22c8392019-06-03 13:59:03 -07001251 if (hostCommand)
1252 {
1253 crow::connections::systemBus->async_method_call(
1254 [asyncResp, resetType](const boost::system::error_code ec) {
1255 if (ec)
1256 {
1257 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1258 if (ec.value() == boost::asio::error::invalid_argument)
1259 {
1260 messages::actionParameterNotSupported(
1261 asyncResp->res, resetType, "Reset");
1262 }
1263 else
1264 {
1265 messages::internalError(asyncResp->res);
1266 }
1267 return;
1268 }
1269 messages::success(asyncResp->res);
1270 },
1271 "xyz.openbmc_project.State.Host",
1272 "/xyz/openbmc_project/state/host0",
1273 "org.freedesktop.DBus.Properties", "Set",
1274 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
1275 std::variant<std::string>{command});
1276 }
1277 else
1278 {
1279 crow::connections::systemBus->async_method_call(
1280 [asyncResp, resetType](const boost::system::error_code ec) {
1281 if (ec)
1282 {
1283 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1284 if (ec.value() == boost::asio::error::invalid_argument)
1285 {
1286 messages::actionParameterNotSupported(
1287 asyncResp->res, resetType, "Reset");
1288 }
1289 else
1290 {
1291 messages::internalError(asyncResp->res);
1292 }
1293 return;
1294 }
1295 messages::success(asyncResp->res);
1296 },
1297 "xyz.openbmc_project.State.Chassis",
1298 "/xyz/openbmc_project/state/chassis0",
1299 "org.freedesktop.DBus.Properties", "Set",
1300 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
1301 std::variant<std::string>{command});
1302 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07001303 }
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001304 /**
1305 * Function transceives data with dbus directly.
1306 */
1307 void doNMI(const std::shared_ptr<AsyncResp> &asyncResp)
1308 {
1309 constexpr char const *serviceName =
1310 "xyz.openbmc_project.Control.Host.NMI";
1311 constexpr char const *objectPath =
1312 "/xyz/openbmc_project/control/host0/nmi";
1313 constexpr char const *interfaceName =
1314 "xyz.openbmc_project.Control.Host.NMI";
1315 constexpr char const *method = "NMI";
1316
1317 crow::connections::systemBus->async_method_call(
1318 [asyncResp](const boost::system::error_code ec) {
1319 if (ec)
1320 {
1321 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
1322 messages::internalError(asyncResp->res);
1323 return;
1324 }
1325 messages::success(asyncResp->res);
1326 },
1327 serviceName, objectPath, interfaceName, method);
1328 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07001329};
1330
1331/**
Ed Tanous66173382018-08-15 18:20:59 -07001332 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001333 */
Ed Tanous1abe55e2018-09-05 08:30:59 -07001334class Systems : public Node
1335{
1336 public:
1337 /*
1338 * Default Constructor
1339 */
Ed Tanous029573d2019-02-01 10:57:49 -08001340 Systems(CrowApp &app) : Node(app, "/redfish/v1/Systems/system/")
Ed Tanous1abe55e2018-09-05 08:30:59 -07001341 {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001342 entityPrivileges = {
1343 {boost::beast::http::verb::get, {{"Login"}}},
1344 {boost::beast::http::verb::head, {{"Login"}}},
1345 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1346 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1347 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1348 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001349 }
1350
Ed Tanous1abe55e2018-09-05 08:30:59 -07001351 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -07001352 /**
1353 * Functions triggers appropriate requests on DBus
1354 */
1355 void doGet(crow::Response &res, const crow::Request &req,
1356 const std::vector<std::string> &params) override
1357 {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301358 res.jsonValue["@odata.type"] = "#ComputerSystem.v1_6_0.ComputerSystem";
Ed Tanous0f74e642018-11-12 15:17:05 -08001359 res.jsonValue["@odata.context"] =
1360 "/redfish/v1/$metadata#ComputerSystem.ComputerSystem";
Ed Tanous029573d2019-02-01 10:57:49 -08001361 res.jsonValue["Name"] = "Computer System";
1362 res.jsonValue["Id"] = "system";
Ed Tanous0f74e642018-11-12 15:17:05 -08001363 res.jsonValue["SystemType"] = "Physical";
1364 res.jsonValue["Description"] = "Computer System";
Ed Tanous0f74e642018-11-12 15:17:05 -08001365 res.jsonValue["ProcessorSummary"]["Count"] = 0;
1366 res.jsonValue["ProcessorSummary"]["Status"]["State"] = "Disabled";
1367 res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] = int(0);
1368 res.jsonValue["MemorySummary"]["Status"]["State"] = "Disabled";
Ed Tanous029573d2019-02-01 10:57:49 -08001369 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07001370
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001371 res.jsonValue["Processors"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001372 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001373 res.jsonValue["Memory"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001374 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
1375
Ed Tanouscc340dd2018-08-29 13:43:38 -07001376 // TODO Need to support ForceRestart.
1377 res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
1378 {"target",
Ed Tanous029573d2019-02-01 10:57:49 -08001379 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
Ed Tanouscc340dd2018-08-29 13:43:38 -07001380 {"ResetType@Redfish.AllowableValues",
Jason M. Billsd22c8392019-06-03 13:59:03 -07001381 {"On", "ForceOff", "ForceOn", "ForceRestart", "GracefulRestart",
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001382 "GracefulShutdown", "PowerCycle", "Nmi"}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001383
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001384 res.jsonValue["LogServices"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001385 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001386
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001387 res.jsonValue["Links"]["ManagedBy"] = {
1388 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
1389
1390 res.jsonValue["Status"] = {
1391 {"Health", "OK"},
1392 {"State", "Enabled"},
1393 };
Ed Tanousa0803ef2018-08-29 13:29:23 -07001394 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001395
James Feistb49ac872019-05-21 15:12:01 -07001396 constexpr const std::array<const char *, 2> inventoryForSystems = {
1397 "xyz.openbmc_project.Inventory.Item.Dimm",
1398 "xyz.openbmc_project.Inventory.Item.Cpu"};
1399
1400 auto health = std::make_shared<HealthPopulate>(asyncResp);
1401 crow::connections::systemBus->async_method_call(
1402 [health](const boost::system::error_code ec,
1403 std::vector<std::string> &resp) {
1404 if (ec)
1405 {
1406 // no inventory
1407 return;
1408 }
1409
1410 health->inventory = std::move(resp);
1411 },
1412 "xyz.openbmc_project.ObjectMapper",
1413 "/xyz/openbmc_project/object_mapper",
1414 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
1415 int32_t(0), inventoryForSystems);
1416
1417 health->populate();
1418
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001419 getMainChassisId(asyncResp, [](const std::string &chassisId,
1420 std::shared_ptr<AsyncResp> aRsp) {
1421 aRsp->res.jsonValue["Links"]["Chassis"] = {
1422 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
1423 });
Ed Tanous6c34de42018-08-29 13:37:36 -07001424 getLedGroupIdentify(
Ed Tanousa0803ef2018-08-29 13:29:23 -07001425 asyncResp,
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001426 [](const bool &asserted, const std::shared_ptr<AsyncResp> aRsp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001427 if (asserted)
1428 {
1429 // If led group is asserted, then another call is needed to
1430 // get led status
Ed Tanous6c34de42018-08-29 13:37:36 -07001431 getLedIdentify(
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001432 aRsp, [](const std::string &ledStatus,
1433 const std::shared_ptr<AsyncResp> aRsp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001434 if (!ledStatus.empty())
1435 {
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001436 aRsp->res.jsonValue["IndicatorLED"] = ledStatus;
Ed Tanous1abe55e2018-09-05 08:30:59 -07001437 }
1438 });
1439 }
1440 else
1441 {
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001442 aRsp->res.jsonValue["IndicatorLED"] = "Off";
Ed Tanous1abe55e2018-09-05 08:30:59 -07001443 }
1444 });
Ed Tanous029573d2019-02-01 10:57:49 -08001445 getComputerSystem(asyncResp);
Ed Tanous6c34de42018-08-29 13:37:36 -07001446 getHostState(asyncResp);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301447 getBootProperties(asyncResp);
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -08001448 getPCIeDeviceList(asyncResp);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001449 }
1450
Ed Tanous1abe55e2018-09-05 08:30:59 -07001451 void doPatch(crow::Response &res, const crow::Request &req,
1452 const std::vector<std::string> &params) override
1453 {
Santosh Puranikcde19e52019-02-20 00:10:56 +05301454 std::optional<std::string> indicatorLed;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301455 std::optional<nlohmann::json> bootProps;
1456 if (!json_util::readJson(req, res, "IndicatorLED", indicatorLed, "Boot",
1457 bootProps))
Ed Tanous66173382018-08-15 18:20:59 -07001458 {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001459 return;
1460 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301461
Ed Tanous029573d2019-02-01 10:57:49 -08001462 auto asyncResp = std::make_shared<AsyncResp>(res);
Jennifer Leed573bb22019-04-10 13:49:51 -07001463 asyncResp->res.result(boost::beast::http::status::no_content);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301464
1465 if (bootProps)
1466 {
1467 std::optional<std::string> bootSource;
1468 std::optional<std::string> bootEnable;
1469
1470 if (!json_util::readJson(*bootProps, asyncResp->res,
1471 "BootSourceOverrideTarget", bootSource,
1472 "BootSourceOverrideEnabled", bootEnable))
1473 {
1474 return;
1475 }
1476 setBootProperties(asyncResp, std::move(bootSource),
1477 std::move(bootEnable));
1478 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001479 if (indicatorLed)
1480 {
1481 std::string dbusLedState;
Jennifer Leed573bb22019-04-10 13:49:51 -07001482 if (*indicatorLed == "Lit")
Ed Tanous66173382018-08-15 18:20:59 -07001483 {
Jennifer Leed573bb22019-04-10 13:49:51 -07001484 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.On";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001485 }
Gunnar Mills5c6221a2019-02-22 11:24:29 -06001486 else if (*indicatorLed == "Blinking")
Ed Tanous9712f8a2018-09-21 13:38:49 -07001487 {
Gunnar Mills5c6221a2019-02-22 11:24:29 -06001488 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.Blink";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001489 }
1490 else if (*indicatorLed == "Off")
1491 {
1492 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.Off";
Ed Tanous66173382018-08-15 18:20:59 -07001493 }
1494 else
1495 {
Jason M. Billsa08b46c2018-11-06 15:01:08 -08001496 messages::propertyValueNotInList(res, *indicatorLed,
1497 "IndicatorLED");
Ed Tanous66173382018-08-15 18:20:59 -07001498 return;
1499 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001500
Ed Tanous9712f8a2018-09-21 13:38:49 -07001501 // Update led group
1502 BMCWEB_LOG_DEBUG << "Update led group.";
1503 crow::connections::systemBus->async_method_call(
Santosh Puranikcde19e52019-02-20 00:10:56 +05301504 [asyncResp](const boost::system::error_code ec) {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001505 if (ec)
1506 {
1507 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -07001508 messages::internalError(asyncResp->res);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001509 return;
1510 }
1511 BMCWEB_LOG_DEBUG << "Led group update done.";
1512 },
1513 "xyz.openbmc_project.LED.GroupManager",
1514 "/xyz/openbmc_project/led/groups/enclosure_identify",
1515 "org.freedesktop.DBus.Properties", "Set",
1516 "xyz.openbmc_project.Led.Group", "Asserted",
Ed Tanousabf2add2019-01-22 16:40:12 -08001517 std::variant<bool>(
Ed Tanous9712f8a2018-09-21 13:38:49 -07001518 (dbusLedState ==
1519 "xyz.openbmc_project.Led.Physical.Action.Off"
1520 ? false
1521 : true)));
1522 // Update identify led status
1523 BMCWEB_LOG_DEBUG << "Update led SoftwareInventoryCollection.";
1524 crow::connections::systemBus->async_method_call(
1525 [asyncResp{std::move(asyncResp)},
1526 indicatorLed{std::move(*indicatorLed)}](
1527 const boost::system::error_code ec) {
1528 if (ec)
1529 {
1530 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -07001531 messages::internalError(asyncResp->res);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001532 return;
1533 }
1534 BMCWEB_LOG_DEBUG << "Led state update done.";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001535 },
1536 "xyz.openbmc_project.LED.Controller.identify",
1537 "/xyz/openbmc_project/led/physical/identify",
1538 "org.freedesktop.DBus.Properties", "Set",
1539 "xyz.openbmc_project.Led.Physical", "State",
Ed Tanousabf2add2019-01-22 16:40:12 -08001540 std::variant<std::string>(dbusLedState));
Ed Tanous1abe55e2018-09-05 08:30:59 -07001541 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001542 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001543};
Ed Tanous1abe55e2018-09-05 08:30:59 -07001544} // namespace redfish