blob: f28ab922365c41ebddb690f9cec7c7d56944980a [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"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080019#include "redfish_util.hpp"
20
Ed Tanous9712f8a2018-09-21 13:38:49 -070021#include <boost/container/flat_map.hpp>
22#include <node.hpp>
Andrew Geisslercb7e1e72019-02-19 13:05:38 -060023#include <utils/fw_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020024#include <utils/json_utils.hpp>
Ed Tanousabf2add2019-01-22 16:40:12 -080025#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020026
Ed Tanous1abe55e2018-09-05 08:30:59 -070027namespace redfish
28{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020029
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020030/**
Ed Tanous6c34de42018-08-29 13:37:36 -070031 * @brief Retrieves computer system properties over dbus
32 *
33 * @param[in] aResp Shared pointer for completing asynchronous calls
34 * @param[in] name Computer system name from request
35 *
36 * @return None.
37 */
Ed Tanous029573d2019-02-01 10:57:49 -080038void getComputerSystem(std::shared_ptr<AsyncResp> aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -070039{
Ed Tanous6c34de42018-08-29 13:37:36 -070040 BMCWEB_LOG_DEBUG << "Get available system components.";
41 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -080042 [aResp](
Ed Tanous6c34de42018-08-29 13:37:36 -070043 const boost::system::error_code ec,
44 const std::vector<std::pair<
45 std::string,
46 std::vector<std::pair<std::string, std::vector<std::string>>>>>
47 &subtree) {
48 if (ec)
49 {
50 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -070051 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -070052 return;
53 }
Ed Tanous6c34de42018-08-29 13:37:36 -070054 // Iterate over all retrieved ObjectPaths.
55 for (const std::pair<std::string,
56 std::vector<std::pair<
57 std::string, std::vector<std::string>>>>
58 &object : subtree)
59 {
60 const std::string &path = object.first;
61 BMCWEB_LOG_DEBUG << "Got path: " << path;
62 const std::vector<
63 std::pair<std::string, std::vector<std::string>>>
64 &connectionNames = object.second;
65 if (connectionNames.size() < 1)
66 {
67 continue;
68 }
Ed Tanous029573d2019-02-01 10:57:49 -080069
70 // This is not system, so check if it's cpu, dimm, UUID or
71 // BiosVer
72 for (const auto &connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -070073 {
Ed Tanous029573d2019-02-01 10:57:49 -080074 for (const auto &interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -070075 {
Ed Tanous029573d2019-02-01 10:57:49 -080076 if (interfaceName ==
77 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -070078 {
Ed Tanous029573d2019-02-01 10:57:49 -080079 BMCWEB_LOG_DEBUG
80 << "Found Dimm, now get its properties.";
81 crow::connections::systemBus->async_method_call(
82 [aResp](const boost::system::error_code ec,
Ed Tanous6c34de42018-08-29 13:37:36 -070083 const std::vector<
84 std::pair<std::string, VariantType>>
85 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -080086 if (ec)
87 {
88 BMCWEB_LOG_ERROR
89 << "DBUS response error " << ec;
90 messages::internalError(aResp->res);
91 return;
92 }
93 BMCWEB_LOG_DEBUG << "Got "
94 << properties.size()
95 << "Dimm properties.";
96 for (const std::pair<std::string,
97 VariantType>
98 &property : properties)
99 {
100 if (property.first == "MemorySizeInKb")
Ed Tanous6c34de42018-08-29 13:37:36 -0700101 {
Ed Tanous029573d2019-02-01 10:57:49 -0800102 const uint64_t *value =
103 sdbusplus::message::variant_ns::
104 get_if<uint64_t>(
105 &property.second);
106 if (value != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700107 {
Ed Tanous029573d2019-02-01 10:57:49 -0800108 aResp->res.jsonValue
109 ["TotalSystemMemoryGi"
110 "B"] +=
111 *value / (1024 * 1024);
112 aResp->res
113 .jsonValue["MemorySummary"]
114 ["Status"]
115 ["State"] =
116 "Enabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700117 }
118 }
Ed Tanous029573d2019-02-01 10:57:49 -0800119 }
120 },
121 connection.first, path,
122 "org.freedesktop.DBus.Properties", "GetAll",
123 "xyz.openbmc_project.Inventory.Item.Dimm");
124 }
125 else if (interfaceName ==
126 "xyz.openbmc_project.Inventory.Item.Cpu")
127 {
128 BMCWEB_LOG_DEBUG
129 << "Found Cpu, now get its properties.";
130 crow::connections::systemBus->async_method_call(
131 [aResp](const boost::system::error_code ec,
Ed Tanous6c34de42018-08-29 13:37:36 -0700132 const std::vector<
133 std::pair<std::string, VariantType>>
134 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800135 if (ec)
136 {
137 BMCWEB_LOG_ERROR
138 << "DBUS response error " << ec;
139 messages::internalError(aResp->res);
140 return;
141 }
142 BMCWEB_LOG_DEBUG << "Got "
143 << properties.size()
144 << "Cpu properties.";
145 for (const auto &property : properties)
146 {
147 if (property.first == "ProcessorFamily")
Ed Tanous6c34de42018-08-29 13:37:36 -0700148 {
Ed Tanous029573d2019-02-01 10:57:49 -0800149 const std::string *value =
150 sdbusplus::message::variant_ns::
151 get_if<std::string>(
152 &property.second);
153 if (value != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700154 {
Ed Tanous029573d2019-02-01 10:57:49 -0800155 nlohmann::json &procSummary =
156 aResp->res.jsonValue
157 ["ProcessorSumm"
158 "ary"];
159 nlohmann::json &procCount =
160 procSummary["Count"];
Ed Tanous04a258f2018-10-15 08:00:41 -0700161
Ed Tanous029573d2019-02-01 10:57:49 -0800162 procCount =
163 procCount.get<int>() + 1;
164 procSummary["Status"]["State"] =
165 "Enabled";
166 procSummary["Model"] = *value;
Ed Tanous6c34de42018-08-29 13:37:36 -0700167 }
168 }
Ed Tanous029573d2019-02-01 10:57:49 -0800169 }
170 },
171 connection.first, path,
172 "org.freedesktop.DBus.Properties", "GetAll",
173 "xyz.openbmc_project.Inventory.Item.Cpu");
174 }
175 else if (interfaceName ==
176 "xyz.openbmc_project.Common.UUID")
177 {
178 BMCWEB_LOG_DEBUG
179 << "Found UUID, now get its properties.";
180 crow::connections::systemBus->async_method_call(
181 [aResp](const boost::system::error_code ec,
Ed Tanous6c34de42018-08-29 13:37:36 -0700182 const std::vector<
183 std::pair<std::string, VariantType>>
184 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800185 if (ec)
186 {
187 BMCWEB_LOG_DEBUG
188 << "DBUS response error " << ec;
189 messages::internalError(aResp->res);
190 return;
191 }
192 BMCWEB_LOG_DEBUG << "Got "
193 << properties.size()
194 << "UUID properties.";
195 for (const std::pair<std::string,
196 VariantType>
197 &property : properties)
198 {
Ed Tanous029573d2019-02-01 10:57:49 -0800199 if (property.first == "UUID")
200 {
201 const std::string *value =
202 sdbusplus::message::variant_ns::
203 get_if<std::string>(
204 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700205
Ed Tanous029573d2019-02-01 10:57:49 -0800206 if (value != nullptr)
207 {
208 std::string valueStr = *value;
209 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700210 {
Ed Tanous029573d2019-02-01 10:57:49 -0800211 valueStr.insert(8, 1, '-');
212 valueStr.insert(13, 1, '-');
213 valueStr.insert(18, 1, '-');
214 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700215 }
Ed Tanous029573d2019-02-01 10:57:49 -0800216 BMCWEB_LOG_DEBUG << "UUID = "
217 << valueStr;
218 aResp->res.jsonValue["UUID"] =
219 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700220 }
221 }
Ed Tanous029573d2019-02-01 10:57:49 -0800222 }
223 },
224 connection.first, path,
225 "org.freedesktop.DBus.Properties", "GetAll",
226 "xyz.openbmc_project.Common.UUID");
227 }
228 else if (interfaceName ==
229 "xyz.openbmc_project.Inventory.Item.System")
230 {
231 crow::connections::systemBus->async_method_call(
232 [aResp](const boost::system::error_code ec,
233 const std::vector<
234 std::pair<std::string, VariantType>>
235 &propertiesList) {
236 if (ec)
237 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700238 // doesn't have to include this
239 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800240 return;
241 }
242 BMCWEB_LOG_DEBUG << "Got "
243 << propertiesList.size()
244 << "properties for system";
245 for (const std::pair<std::string,
246 VariantType>
247 &property : propertiesList)
248 {
beccabroekfc5afcf2019-03-05 14:35:15 -0600249 const std::string &propertyName =
250 property.first;
251 if ((propertyName == "PartNumber") ||
252 (propertyName == "SerialNumber") ||
253 (propertyName == "Manufacturer") ||
254 (propertyName == "Model"))
Ed Tanous029573d2019-02-01 10:57:49 -0800255 {
beccabroekfc5afcf2019-03-05 14:35:15 -0600256 const std::string *value =
257 std::get_if<std::string>(
258 &property.second);
259 if (value != nullptr)
260 {
261 aResp->res
262 .jsonValue[propertyName] =
263 *value;
264 }
Ed Tanous029573d2019-02-01 10:57:49 -0800265 }
266 }
267 aResp->res.jsonValue["Name"] = "system";
268 aResp->res.jsonValue["Id"] =
269 aResp->res.jsonValue["SerialNumber"];
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600270 // Grab the bios version
271 fw_util::getActiveFwVersion(
272 aResp, fw_util::biosPurpose,
273 "BiosVersion");
Ed Tanous029573d2019-02-01 10:57:49 -0800274 },
275 connection.first, path,
276 "org.freedesktop.DBus.Properties", "GetAll",
277 "xyz.openbmc_project.Inventory.Decorator."
278 "Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700279
280 crow::connections::systemBus->async_method_call(
281 [aResp](
282 const boost::system::error_code ec,
283 const std::variant<std::string> &property) {
284 if (ec)
285 {
286 // doesn't have to include this
287 // interface
288 return;
289 }
290
291 const std::string *value =
292 std::get_if<std::string>(&property);
293 if (value != nullptr)
294 {
295 aResp->res.jsonValue["AssetTag"] =
296 *value;
297 }
298 },
299 connection.first, path,
300 "org.freedesktop.DBus.Properties", "Get",
301 "xyz.openbmc_project.Inventory.Decorator."
302 "AssetTag",
303 "AssetTag");
Ed Tanous6c34de42018-08-29 13:37:36 -0700304 }
305 }
306 }
307 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700308 },
309 "xyz.openbmc_project.ObjectMapper",
310 "/xyz/openbmc_project/object_mapper",
311 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700312 "/xyz/openbmc_project/inventory", int32_t(0),
313 std::array<const char *, 5>{
314 "xyz.openbmc_project.Inventory.Decorator.Asset",
315 "xyz.openbmc_project.Inventory.Item.Cpu",
316 "xyz.openbmc_project.Inventory.Item.Dimm",
317 "xyz.openbmc_project.Inventory.Item.System",
318 "xyz.openbmc_project.Common.UUID",
319 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700320}
321
322/**
323 * @brief Retrieves identify led group properties over dbus
324 *
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530325 * @param[in] aResp Shared pointer for generating response message.
Ed Tanous6c34de42018-08-29 13:37:36 -0700326 * @param[in] callback Callback for process retrieved data.
327 *
328 * @return None.
329 */
330template <typename CallbackFunc>
331void getLedGroupIdentify(std::shared_ptr<AsyncResp> aResp,
332 CallbackFunc &&callback)
333{
334 BMCWEB_LOG_DEBUG << "Get led groups";
335 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800336 [aResp,
Ed Tanous66173382018-08-15 18:20:59 -0700337 callback{std::move(callback)}](const boost::system::error_code &ec,
338 const ManagedObjectsType &resp) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700339 if (ec)
340 {
341 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700342 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700343 return;
344 }
345 BMCWEB_LOG_DEBUG << "Got " << resp.size() << "led group objects.";
346 for (const auto &objPath : resp)
347 {
348 const std::string &path = objPath.first;
349 if (path.rfind("enclosure_identify") != std::string::npos)
350 {
351 for (const auto &interface : objPath.second)
352 {
353 if (interface.first == "xyz.openbmc_project.Led.Group")
354 {
355 for (const auto &property : interface.second)
356 {
357 if (property.first == "Asserted")
358 {
359 const bool *asserted =
Ed Tanousabf2add2019-01-22 16:40:12 -0800360 std::get_if<bool>(&property.second);
Ed Tanous6c34de42018-08-29 13:37:36 -0700361 if (nullptr != asserted)
362 {
363 callback(*asserted, aResp);
364 }
365 else
366 {
367 callback(false, aResp);
368 }
369 }
370 }
371 }
372 }
373 }
374 }
375 },
376 "xyz.openbmc_project.LED.GroupManager",
377 "/xyz/openbmc_project/led/groups", "org.freedesktop.DBus.ObjectManager",
378 "GetManagedObjects");
379}
380
381template <typename CallbackFunc>
382void getLedIdentify(std::shared_ptr<AsyncResp> aResp, CallbackFunc &&callback)
383{
384 BMCWEB_LOG_DEBUG << "Get identify led properties";
385 crow::connections::systemBus->async_method_call(
Ed Tanous66173382018-08-15 18:20:59 -0700386 [aResp,
387 callback{std::move(callback)}](const boost::system::error_code ec,
388 const PropertiesType &properties) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700389 if (ec)
390 {
391 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700392 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700393 return;
394 }
395 BMCWEB_LOG_DEBUG << "Got " << properties.size()
396 << "led properties.";
397 std::string output;
398 for (const auto &property : properties)
399 {
400 if (property.first == "State")
401 {
402 const std::string *s =
Ed Tanousabf2add2019-01-22 16:40:12 -0800403 std::get_if<std::string>(&property.second);
Ed Tanous6c34de42018-08-29 13:37:36 -0700404 if (nullptr != s)
405 {
406 BMCWEB_LOG_DEBUG << "Identify Led State: " << *s;
407 const auto pos = s->rfind('.');
408 if (pos != std::string::npos)
409 {
410 auto led = s->substr(pos + 1);
411 for (const std::pair<const char *, const char *>
412 &p :
413 std::array<
414 std::pair<const char *, const char *>, 3>{
415 {{"On", "Lit"},
416 {"Blink", "Blinking"},
417 {"Off", "Off"}}})
418 {
419 if (led == p.first)
420 {
421 output = p.second;
422 }
423 }
424 }
425 }
426 }
427 }
428 callback(output, aResp);
429 },
430 "xyz.openbmc_project.LED.Controller.identify",
431 "/xyz/openbmc_project/led/physical/identify",
432 "org.freedesktop.DBus.Properties", "GetAll",
433 "xyz.openbmc_project.Led.Physical");
434}
Ed Tanous6c34de42018-08-29 13:37:36 -0700435/**
436 * @brief Retrieves host state properties over dbus
437 *
438 * @param[in] aResp Shared pointer for completing asynchronous calls.
439 *
440 * @return None.
441 */
442void getHostState(std::shared_ptr<AsyncResp> aResp)
443{
444 BMCWEB_LOG_DEBUG << "Get host information.";
445 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800446 [aResp](const boost::system::error_code ec,
447 const std::variant<std::string> &hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700448 if (ec)
449 {
450 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700451 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700452 return;
453 }
Ed Tanous66173382018-08-15 18:20:59 -0700454
Ed Tanousabf2add2019-01-22 16:40:12 -0800455 const std::string *s = std::get_if<std::string>(&hostState);
Ed Tanous66173382018-08-15 18:20:59 -0700456 BMCWEB_LOG_DEBUG << "Host state: " << *s;
457 if (s != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700458 {
Ed Tanous66173382018-08-15 18:20:59 -0700459 // Verify Host State
Andrew Geissler94732662019-01-08 19:32:16 -0800460 if (*s == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700461 {
Ed Tanous66173382018-08-15 18:20:59 -0700462 aResp->res.jsonValue["PowerState"] = "On";
463 aResp->res.jsonValue["Status"]["State"] = "Enabled";
464 }
465 else
466 {
467 aResp->res.jsonValue["PowerState"] = "Off";
468 aResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700469 }
470 }
471 },
472 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Ed Tanous66173382018-08-15 18:20:59 -0700473 "org.freedesktop.DBus.Properties", "Get",
474 "xyz.openbmc_project.State.Host", "CurrentHostState");
Ed Tanous6c34de42018-08-29 13:37:36 -0700475}
476
477/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530478 * @brief Traslates boot source DBUS property value to redfish.
479 *
480 * @param[in] dbusSource The boot source in DBUS speak.
481 *
482 * @return Returns as a string, the boot source in Redfish terms. If translation
483 * cannot be done, returns an empty string.
484 */
485static std::string dbusToRfBootSource(const std::string &dbusSource)
486{
487 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
488 {
489 return "None";
490 }
491 else if (dbusSource ==
492 "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
493 {
494 return "Hdd";
495 }
496 else if (dbusSource ==
Santosh Puranika71dc0b2019-05-23 20:10:49 +0530497 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530498 {
499 return "Cd";
500 }
501 else if (dbusSource ==
502 "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
503 {
504 return "Pxe";
505 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700506 else if (dbusSource ==
507 "xyz.openbmc_project.Control.Boot.Source.Sources.Removable")
508 {
509 return "Usb";
510 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530511 else
512 {
513 return "";
514 }
515}
516
517/**
518 * @brief Traslates boot mode DBUS property value to redfish.
519 *
520 * @param[in] dbusMode The boot mode in DBUS speak.
521 *
522 * @return Returns as a string, the boot mode in Redfish terms. If translation
523 * cannot be done, returns an empty string.
524 */
525static std::string dbusToRfBootMode(const std::string &dbusMode)
526{
527 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
528 {
529 return "None";
530 }
531 else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
532 {
533 return "Diags";
534 }
535 else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
536 {
537 return "BiosSetup";
538 }
539 else
540 {
541 return "";
542 }
543}
544
545/**
546 * @brief Traslates boot source from Redfish to DBUS property value.
547 *
548 * @param[in] rfSource The boot source in Redfish.
549 *
550 * @return Returns as a string, the boot source as expected by DBUS.
551 * If translation cannot be done, returns an empty string.
552 */
553static std::string rfToDbusBootSource(const std::string &rfSource)
554{
555 if (rfSource == "None")
556 {
557 return "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
558 }
559 else if (rfSource == "Hdd")
560 {
561 return "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
562 }
563 else if (rfSource == "Cd")
564 {
Santosh Puranika71dc0b2019-05-23 20:10:49 +0530565 return "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530566 }
567 else if (rfSource == "Pxe")
568 {
569 return "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
570 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700571 else if (rfSource == "Usb")
572 {
573 return "xyz.openbmc_project.Control.Boot.Source.Sources.Removable";
574 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530575 else
576 {
577 return "";
578 }
579}
580
581/**
582 * @brief Traslates boot mode from Redfish to DBUS property value.
583 *
584 * @param[in] rfMode The boot mode in Redfish.
585 *
586 * @return Returns as a string, the boot mode as expected by DBUS.
587 * If translation cannot be done, returns an empty string.
588 */
589static std::string rfToDbusBootMode(const std::string &rfMode)
590{
591 if (rfMode == "None")
592 {
593 return "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
594 }
595 else if (rfMode == "Diags")
596 {
597 return "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
598 }
599 else if (rfMode == "BiosSetup")
600 {
601 return "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
602 }
603 else
604 {
605 return "";
606 }
607}
608
609/**
610 * @brief Retrieves boot mode over DBUS and fills out the response
611 *
612 * @param[in] aResp Shared pointer for generating response message.
613 * @param[in] bootDbusObj The dbus object to query for boot properties.
614 *
615 * @return None.
616 */
617static void getBootMode(std::shared_ptr<AsyncResp> aResp,
618 std::string bootDbusObj)
619{
620 crow::connections::systemBus->async_method_call(
621 [aResp](const boost::system::error_code ec,
622 const std::variant<std::string> &bootMode) {
623 if (ec)
624 {
625 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
626 messages::internalError(aResp->res);
627 return;
628 }
629
630 const std::string *bootModeStr =
631 std::get_if<std::string>(&bootMode);
632
633 if (!bootModeStr)
634 {
635 messages::internalError(aResp->res);
636 return;
637 }
638
639 BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
640
641 // TODO (Santosh): Do we need to support override mode?
642 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = "Legacy";
643 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
644 "AllowableValues"] = {
645 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup"};
646
647 if (*bootModeStr !=
648 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
649 {
650 auto rfMode = dbusToRfBootMode(*bootModeStr);
651 if (!rfMode.empty())
652 {
653 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
654 rfMode;
655 }
656 }
657
658 // If the BootSourceOverrideTarget is still "None" at the end,
659 // reset the BootSourceOverrideEnabled to indicate that
660 // overrides are disabled
661 if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] ==
662 "None")
663 {
664 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
665 "Disabled";
666 }
667 },
668 "xyz.openbmc_project.Settings", bootDbusObj,
669 "org.freedesktop.DBus.Properties", "Get",
670 "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
671}
672
673/**
674 * @brief Retrieves boot source over DBUS
675 *
676 * @param[in] aResp Shared pointer for generating response message.
677 * @param[in] oneTimeEnable Boolean to indicate boot properties are one-time.
678 *
679 * @return None.
680 */
681static void getBootSource(std::shared_ptr<AsyncResp> aResp, bool oneTimeEnabled)
682{
683 std::string bootDbusObj =
684 oneTimeEnabled ? "/xyz/openbmc_project/control/host0/boot/one_time"
685 : "/xyz/openbmc_project/control/host0/boot";
686
687 BMCWEB_LOG_DEBUG << "Is one time: " << oneTimeEnabled;
688 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
689 (oneTimeEnabled) ? "Once" : "Continuous";
690
691 crow::connections::systemBus->async_method_call(
692 [aResp, bootDbusObj](const boost::system::error_code ec,
693 const std::variant<std::string> &bootSource) {
694 if (ec)
695 {
696 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
697 messages::internalError(aResp->res);
698 return;
699 }
700
701 const std::string *bootSourceStr =
702 std::get_if<std::string>(&bootSource);
703
704 if (!bootSourceStr)
705 {
706 messages::internalError(aResp->res);
707 return;
708 }
709 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
710
711 auto rfSource = dbusToRfBootSource(*bootSourceStr);
712 if (!rfSource.empty())
713 {
714 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
715 rfSource;
716 }
717 },
718 "xyz.openbmc_project.Settings", bootDbusObj,
719 "org.freedesktop.DBus.Properties", "Get",
720 "xyz.openbmc_project.Control.Boot.Source", "BootSource");
721 getBootMode(std::move(aResp), std::move(bootDbusObj));
722}
723
724/**
725 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
726 * get boot source and boot mode.
727 *
728 * @param[in] aResp Shared pointer for generating response message.
729 *
730 * @return None.
731 */
732static void getBootProperties(std::shared_ptr<AsyncResp> aResp)
733{
734 BMCWEB_LOG_DEBUG << "Get boot information.";
735
736 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800737 [aResp](const boost::system::error_code ec,
738 const sdbusplus::message::variant<bool> &oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530739 if (ec)
740 {
741 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
742 messages::internalError(aResp->res);
743 return;
744 }
745
746 const bool *oneTimePtr = std::get_if<bool>(&oneTime);
747
748 if (!oneTimePtr)
749 {
750 messages::internalError(aResp->res);
751 return;
752 }
753 getBootSource(aResp, *oneTimePtr);
754 },
755 "xyz.openbmc_project.Settings",
756 "/xyz/openbmc_project/control/host0/boot/one_time",
757 "org.freedesktop.DBus.Properties", "Get",
758 "xyz.openbmc_project.Object.Enable", "Enabled");
759}
760
761/**
762 * @brief Sets boot properties into DBUS object(s).
763 *
764 * @param[in] aResp Shared pointer for generating response message.
765 * @param[in] oneTimeEnabled Is "one-time" setting already enabled.
766 * @param[in] bootSource The boot source to set.
767 * @param[in] bootEnable The source override "enable" to set.
768 *
769 * @return None.
770 */
771static void setBootModeOrSource(std::shared_ptr<AsyncResp> aResp,
772 bool oneTimeEnabled,
773 std::optional<std::string> bootSource,
774 std::optional<std::string> bootEnable)
775{
776 if (bootEnable && (bootEnable != "Once") && (bootEnable != "Continuous") &&
777 (bootEnable != "Disabled"))
778 {
779 BMCWEB_LOG_DEBUG << "Unsupported value for BootSourceOverrideEnabled: "
780 << *bootEnable;
781 messages::propertyValueNotInList(aResp->res, *bootEnable,
782 "BootSourceOverrideEnabled");
783 return;
784 }
785
786 bool oneTimeSetting = oneTimeEnabled;
787 // Validate incoming parameters
788 if (bootEnable)
789 {
790 if (*bootEnable == "Once")
791 {
792 oneTimeSetting = true;
793 }
794 else if (*bootEnable == "Continuous")
795 {
796 oneTimeSetting = false;
797 }
798 else if (*bootEnable == "Disabled")
799 {
800 oneTimeSetting = false;
801 }
802 else
803 {
804
805 BMCWEB_LOG_DEBUG << "Unsupported value for "
806 "BootSourceOverrideEnabled: "
807 << *bootEnable;
808 messages::propertyValueNotInList(aResp->res, *bootEnable,
809 "BootSourceOverrideEnabled");
810 return;
811 }
812 }
813 std::string bootSourceStr;
814 std::string bootModeStr;
815 if (bootSource)
816 {
817 bootSourceStr = rfToDbusBootSource(*bootSource);
818 bootModeStr = rfToDbusBootMode(*bootSource);
819
820 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
821 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
822
823 if (bootSourceStr.empty() && bootModeStr.empty())
824 {
825 BMCWEB_LOG_DEBUG << "Invalid property value for "
826 "BootSourceOverrideTarget: "
827 << *bootSource;
828 messages::propertyValueNotInList(aResp->res, *bootSource,
829 "BootSourceTargetOverride");
830 return;
831 }
832 }
833 const char *bootObj =
834 oneTimeSetting ? "/xyz/openbmc_project/control/host0/boot/one_time"
835 : "/xyz/openbmc_project/control/host0/boot";
836 // Figure out what properties to set
837 if (bootEnable && (*bootEnable == "Disabled"))
838 {
839 BMCWEB_LOG_DEBUG << "Boot source override will be disabled";
840 // Request to only turn OFF/ON enabled, if turning enabled OFF, need
841 // to reset the source and mode too. If turning it ON, we only need
842 // to set the enabled property
843 bootSourceStr =
844 "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
845 bootModeStr = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
846 }
847 else if (bootSource)
848 {
849 // Source target specified
850 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
851 // Figure out which DBUS interface and property to use
852 bootSourceStr = rfToDbusBootSource(*bootSource);
853 bootModeStr = rfToDbusBootMode(*bootSource);
854
855 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
856 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
857
858 if (bootSourceStr.empty() && bootModeStr.empty())
859 {
860 BMCWEB_LOG_DEBUG << "Invalid property value for "
861 "BootSourceOverrideTarget: "
862 << *bootSource;
863 messages::propertyValueNotInList(aResp->res, *bootSource,
864 "BootSourceTargetOverride");
865 return;
866 }
867
868 if (!bootSourceStr.empty())
869 {
870 // If setting to anything other than default, also reset boot
871 // mode property
872 if (bootSourceStr !=
873 "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
874 {
875 bootModeStr =
876 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
877 }
878 }
879 else // if (!bootModeStr.empty())
880 {
881 // If setting to anything other than default, also reset boot
882 // source property
883 if (bootModeStr !=
884 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
885 {
886 bootSourceStr =
887 "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
888 }
889 }
890 }
891 if (!bootSourceStr.empty())
892 {
893 crow::connections::systemBus->async_method_call(
894 [aResp](const boost::system::error_code ec) {
895 if (ec)
896 {
897 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
898 messages::internalError(aResp->res);
899 return;
900 }
901 BMCWEB_LOG_DEBUG << "Boot source update done.";
902 },
903 "xyz.openbmc_project.Settings", bootObj,
904 "org.freedesktop.DBus.Properties", "Set",
905 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
906 std::variant<std::string>(bootSourceStr));
907 }
908 if (!bootModeStr.empty())
909 {
910 crow::connections::systemBus->async_method_call(
911 [aResp](const boost::system::error_code ec) {
912 if (ec)
913 {
914 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
915 messages::internalError(aResp->res);
916 return;
917 }
918 BMCWEB_LOG_DEBUG << "Boot mode update done.";
919 },
920 "xyz.openbmc_project.Settings", bootObj,
921 "org.freedesktop.DBus.Properties", "Set",
922 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
923 std::variant<std::string>(bootModeStr));
924 }
925 crow::connections::systemBus->async_method_call(
926 [aResp{std::move(aResp)}](const boost::system::error_code ec) {
927 if (ec)
928 {
929 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
930 messages::internalError(aResp->res);
931 return;
932 }
933 BMCWEB_LOG_DEBUG << "Boot enable update done.";
934 },
935 "xyz.openbmc_project.Settings",
936 "/xyz/openbmc_project/control/host0/boot/one_time",
937 "org.freedesktop.DBus.Properties", "Set",
938 "xyz.openbmc_project.Object.Enable", "Enabled",
939 std::variant<bool>(oneTimeSetting));
940}
941
942/**
943 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
944 * set boot source/boot mode properties.
945 *
946 * @param[in] aResp Shared pointer for generating response message.
947 * @param[in] bootSource The boot source from incoming RF request.
948 * @param[in] bootEnable The boot override enable from incoming RF request.
949 *
950 * @return None.
951 */
952static void setBootProperties(std::shared_ptr<AsyncResp> aResp,
953 std::optional<std::string> bootSource,
954 std::optional<std::string> bootEnable)
955{
956 BMCWEB_LOG_DEBUG << "Set boot information.";
957
958 crow::connections::systemBus->async_method_call(
959 [aResp{std::move(aResp)}, bootSource{std::move(bootSource)},
960 bootEnable{std::move(bootEnable)}](
961 const boost::system::error_code ec,
962 const sdbusplus::message::variant<bool> &oneTime) {
963 if (ec)
964 {
965 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
966 messages::internalError(aResp->res);
967 return;
968 }
969
970 const bool *oneTimePtr = std::get_if<bool>(&oneTime);
971
972 if (!oneTimePtr)
973 {
974 messages::internalError(aResp->res);
975 return;
976 }
977
978 BMCWEB_LOG_DEBUG << "Got one time: " << *oneTimePtr;
979
980 setBootModeOrSource(aResp, *oneTimePtr, std::move(bootSource),
981 std::move(bootEnable));
982 },
983 "xyz.openbmc_project.Settings",
984 "/xyz/openbmc_project/control/host0/boot/one_time",
985 "org.freedesktop.DBus.Properties", "Get",
986 "xyz.openbmc_project.Object.Enable", "Enabled");
987}
988
989/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +0200990 * SystemsCollection derived class for delivering ComputerSystems Collection
991 * Schema
992 */
Ed Tanous1abe55e2018-09-05 08:30:59 -0700993class SystemsCollection : public Node
994{
995 public:
996 SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/")
997 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700998 entityPrivileges = {
999 {boost::beast::http::verb::get, {{"Login"}}},
1000 {boost::beast::http::verb::head, {{"Login"}}},
1001 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1002 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1003 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1004 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1005 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001006
Ed Tanous1abe55e2018-09-05 08:30:59 -07001007 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -07001008 void doGet(crow::Response &res, const crow::Request &req,
1009 const std::vector<std::string> &params) override
1010 {
Ed Tanous0f74e642018-11-12 15:17:05 -08001011 res.jsonValue["@odata.type"] =
1012 "#ComputerSystemCollection.ComputerSystemCollection";
1013 res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
1014 res.jsonValue["@odata.context"] =
1015 "/redfish/v1/"
1016 "$metadata#ComputerSystemCollection.ComputerSystemCollection";
1017 res.jsonValue["Name"] = "Computer System Collection";
Ed Tanous029573d2019-02-01 10:57:49 -08001018 res.jsonValue["Members"] = {
1019 {{"@odata.id", "/redfish/v1/Systems/system"}}};
1020 res.jsonValue["Members@odata.count"] = 1;
1021 res.end();
Ed Tanous1abe55e2018-09-05 08:30:59 -07001022 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001023};
1024
1025/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07001026 * SystemActionsReset class supports handle POST method for Reset action.
1027 * The class retrieves and sends data directly to D-Bus.
1028 */
1029class SystemActionsReset : public Node
1030{
1031 public:
1032 SystemActionsReset(CrowApp &app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001033 Node(app, "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanouscc340dd2018-08-29 13:43:38 -07001034 {
1035 entityPrivileges = {
1036 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1037 }
1038
1039 private:
1040 /**
1041 * Function handles POST method request.
1042 * Analyzes POST body message before sends Reset request data to D-Bus.
1043 */
1044 void doPost(crow::Response &res, const crow::Request &req,
1045 const std::vector<std::string> &params) override
1046 {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001047 auto asyncResp = std::make_shared<AsyncResp>(res);
1048
1049 std::string resetType;
1050 if (!json_util::readJson(req, res, "ResetType", resetType))
Ed Tanouscc340dd2018-08-29 13:43:38 -07001051 {
1052 return;
1053 }
1054
Jason M. Billsd22c8392019-06-03 13:59:03 -07001055 // Get the command and host vs. chassis
Ed Tanous9712f8a2018-09-21 13:38:49 -07001056 std::string command;
Jason M. Billsd22c8392019-06-03 13:59:03 -07001057 bool hostCommand;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001058 if (resetType == "On")
1059 {
1060 command = "xyz.openbmc_project.State.Host.Transition.On";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001061 hostCommand = true;
1062 }
1063 else if (resetType == "ForceOff")
1064 {
1065 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
1066 hostCommand = false;
1067 }
1068 else if (resetType == "ForceOn")
1069 {
1070 command = "xyz.openbmc_project.State.Host.Transition.On";
1071 hostCommand = true;
1072 }
1073 else if (resetType == "ForceRestart")
1074 {
1075 command = "xyz.openbmc_project.State.Chassis.Transition.Reset";
1076 hostCommand = false;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001077 }
1078 else if (resetType == "GracefulShutdown")
1079 {
1080 command = "xyz.openbmc_project.State.Host.Transition.Off";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001081 hostCommand = true;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001082 }
1083 else if (resetType == "GracefulRestart")
1084 {
1085 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001086 hostCommand = true;
1087 }
1088 else if (resetType == "PowerCycle")
1089 {
1090 command = "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
1091 hostCommand = false;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001092 }
1093 else
1094 {
Jason M. Billsf12894f2018-10-09 12:45:45 -07001095 messages::actionParameterUnknown(res, "Reset", resetType);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001096 return;
1097 }
1098
Jason M. Billsd22c8392019-06-03 13:59:03 -07001099 if (hostCommand)
1100 {
1101 crow::connections::systemBus->async_method_call(
1102 [asyncResp, resetType](const boost::system::error_code ec) {
1103 if (ec)
1104 {
1105 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1106 if (ec.value() == boost::asio::error::invalid_argument)
1107 {
1108 messages::actionParameterNotSupported(
1109 asyncResp->res, resetType, "Reset");
1110 }
1111 else
1112 {
1113 messages::internalError(asyncResp->res);
1114 }
1115 return;
1116 }
1117 messages::success(asyncResp->res);
1118 },
1119 "xyz.openbmc_project.State.Host",
1120 "/xyz/openbmc_project/state/host0",
1121 "org.freedesktop.DBus.Properties", "Set",
1122 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
1123 std::variant<std::string>{command});
1124 }
1125 else
1126 {
1127 crow::connections::systemBus->async_method_call(
1128 [asyncResp, resetType](const boost::system::error_code ec) {
1129 if (ec)
1130 {
1131 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1132 if (ec.value() == boost::asio::error::invalid_argument)
1133 {
1134 messages::actionParameterNotSupported(
1135 asyncResp->res, resetType, "Reset");
1136 }
1137 else
1138 {
1139 messages::internalError(asyncResp->res);
1140 }
1141 return;
1142 }
1143 messages::success(asyncResp->res);
1144 },
1145 "xyz.openbmc_project.State.Chassis",
1146 "/xyz/openbmc_project/state/chassis0",
1147 "org.freedesktop.DBus.Properties", "Set",
1148 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
1149 std::variant<std::string>{command});
1150 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07001151 }
1152};
1153
1154/**
Ed Tanous66173382018-08-15 18:20:59 -07001155 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001156 */
Ed Tanous1abe55e2018-09-05 08:30:59 -07001157class Systems : public Node
1158{
1159 public:
1160 /*
1161 * Default Constructor
1162 */
Ed Tanous029573d2019-02-01 10:57:49 -08001163 Systems(CrowApp &app) : Node(app, "/redfish/v1/Systems/system/")
Ed Tanous1abe55e2018-09-05 08:30:59 -07001164 {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001165 entityPrivileges = {
1166 {boost::beast::http::verb::get, {{"Login"}}},
1167 {boost::beast::http::verb::head, {{"Login"}}},
1168 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1169 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1170 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1171 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001172 }
1173
Ed Tanous1abe55e2018-09-05 08:30:59 -07001174 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -07001175 /**
1176 * Functions triggers appropriate requests on DBus
1177 */
1178 void doGet(crow::Response &res, const crow::Request &req,
1179 const std::vector<std::string> &params) override
1180 {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301181 res.jsonValue["@odata.type"] = "#ComputerSystem.v1_6_0.ComputerSystem";
Ed Tanous0f74e642018-11-12 15:17:05 -08001182 res.jsonValue["@odata.context"] =
1183 "/redfish/v1/$metadata#ComputerSystem.ComputerSystem";
Ed Tanous029573d2019-02-01 10:57:49 -08001184 res.jsonValue["Name"] = "Computer System";
1185 res.jsonValue["Id"] = "system";
Ed Tanous0f74e642018-11-12 15:17:05 -08001186 res.jsonValue["SystemType"] = "Physical";
1187 res.jsonValue["Description"] = "Computer System";
Ed Tanous0f74e642018-11-12 15:17:05 -08001188 res.jsonValue["ProcessorSummary"]["Count"] = 0;
1189 res.jsonValue["ProcessorSummary"]["Status"]["State"] = "Disabled";
1190 res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] = int(0);
1191 res.jsonValue["MemorySummary"]["Status"]["State"] = "Disabled";
Ed Tanous029573d2019-02-01 10:57:49 -08001192 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07001193
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001194 res.jsonValue["Processors"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001195 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001196 res.jsonValue["Memory"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001197 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
1198
Ed Tanouscc340dd2018-08-29 13:43:38 -07001199 // TODO Need to support ForceRestart.
1200 res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
1201 {"target",
Ed Tanous029573d2019-02-01 10:57:49 -08001202 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
Ed Tanouscc340dd2018-08-29 13:43:38 -07001203 {"ResetType@Redfish.AllowableValues",
Jason M. Billsd22c8392019-06-03 13:59:03 -07001204 {"On", "ForceOff", "ForceOn", "ForceRestart", "GracefulRestart",
1205 "GracefulShutdown", "PowerCycle"}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001206
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001207 res.jsonValue["LogServices"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001208 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001209
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001210 res.jsonValue["Links"]["ManagedBy"] = {
1211 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
1212
1213 res.jsonValue["Status"] = {
1214 {"Health", "OK"},
1215 {"State", "Enabled"},
1216 };
Ed Tanousa0803ef2018-08-29 13:29:23 -07001217 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001218
James Feistb49ac872019-05-21 15:12:01 -07001219 constexpr const std::array<const char *, 2> inventoryForSystems = {
1220 "xyz.openbmc_project.Inventory.Item.Dimm",
1221 "xyz.openbmc_project.Inventory.Item.Cpu"};
1222
1223 auto health = std::make_shared<HealthPopulate>(asyncResp);
1224 crow::connections::systemBus->async_method_call(
1225 [health](const boost::system::error_code ec,
1226 std::vector<std::string> &resp) {
1227 if (ec)
1228 {
1229 // no inventory
1230 return;
1231 }
1232
1233 health->inventory = std::move(resp);
1234 },
1235 "xyz.openbmc_project.ObjectMapper",
1236 "/xyz/openbmc_project/object_mapper",
1237 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
1238 int32_t(0), inventoryForSystems);
1239
1240 health->populate();
1241
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001242 getMainChassisId(asyncResp, [](const std::string &chassisId,
1243 std::shared_ptr<AsyncResp> aRsp) {
1244 aRsp->res.jsonValue["Links"]["Chassis"] = {
1245 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
1246 });
Ed Tanous6c34de42018-08-29 13:37:36 -07001247 getLedGroupIdentify(
Ed Tanousa0803ef2018-08-29 13:29:23 -07001248 asyncResp,
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001249 [](const bool &asserted, const std::shared_ptr<AsyncResp> aRsp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001250 if (asserted)
1251 {
1252 // If led group is asserted, then another call is needed to
1253 // get led status
Ed Tanous6c34de42018-08-29 13:37:36 -07001254 getLedIdentify(
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001255 aRsp, [](const std::string &ledStatus,
1256 const std::shared_ptr<AsyncResp> aRsp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001257 if (!ledStatus.empty())
1258 {
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001259 aRsp->res.jsonValue["IndicatorLED"] = ledStatus;
Ed Tanous1abe55e2018-09-05 08:30:59 -07001260 }
1261 });
1262 }
1263 else
1264 {
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001265 aRsp->res.jsonValue["IndicatorLED"] = "Off";
Ed Tanous1abe55e2018-09-05 08:30:59 -07001266 }
1267 });
Ed Tanous029573d2019-02-01 10:57:49 -08001268 getComputerSystem(asyncResp);
Ed Tanous6c34de42018-08-29 13:37:36 -07001269 getHostState(asyncResp);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301270 getBootProperties(asyncResp);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001271 }
1272
Ed Tanous1abe55e2018-09-05 08:30:59 -07001273 void doPatch(crow::Response &res, const crow::Request &req,
1274 const std::vector<std::string> &params) override
1275 {
Santosh Puranikcde19e52019-02-20 00:10:56 +05301276 std::optional<std::string> indicatorLed;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301277 std::optional<nlohmann::json> bootProps;
1278 if (!json_util::readJson(req, res, "IndicatorLED", indicatorLed, "Boot",
1279 bootProps))
Ed Tanous66173382018-08-15 18:20:59 -07001280 {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001281 return;
1282 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301283
Ed Tanous029573d2019-02-01 10:57:49 -08001284 auto asyncResp = std::make_shared<AsyncResp>(res);
Jennifer Leed573bb22019-04-10 13:49:51 -07001285 asyncResp->res.result(boost::beast::http::status::no_content);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301286
1287 if (bootProps)
1288 {
1289 std::optional<std::string> bootSource;
1290 std::optional<std::string> bootEnable;
1291
1292 if (!json_util::readJson(*bootProps, asyncResp->res,
1293 "BootSourceOverrideTarget", bootSource,
1294 "BootSourceOverrideEnabled", bootEnable))
1295 {
1296 return;
1297 }
1298 setBootProperties(asyncResp, std::move(bootSource),
1299 std::move(bootEnable));
1300 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001301 if (indicatorLed)
1302 {
1303 std::string dbusLedState;
Jennifer Leed573bb22019-04-10 13:49:51 -07001304 if (*indicatorLed == "Lit")
Ed Tanous66173382018-08-15 18:20:59 -07001305 {
Jennifer Leed573bb22019-04-10 13:49:51 -07001306 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.On";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001307 }
Gunnar Mills5c6221a2019-02-22 11:24:29 -06001308 else if (*indicatorLed == "Blinking")
Ed Tanous9712f8a2018-09-21 13:38:49 -07001309 {
Gunnar Mills5c6221a2019-02-22 11:24:29 -06001310 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.Blink";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001311 }
1312 else if (*indicatorLed == "Off")
1313 {
1314 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.Off";
Ed Tanous66173382018-08-15 18:20:59 -07001315 }
1316 else
1317 {
Jason M. Billsa08b46c2018-11-06 15:01:08 -08001318 messages::propertyValueNotInList(res, *indicatorLed,
1319 "IndicatorLED");
Ed Tanous66173382018-08-15 18:20:59 -07001320 return;
1321 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001322
Ed Tanous9712f8a2018-09-21 13:38:49 -07001323 // Update led group
1324 BMCWEB_LOG_DEBUG << "Update led group.";
1325 crow::connections::systemBus->async_method_call(
Santosh Puranikcde19e52019-02-20 00:10:56 +05301326 [asyncResp](const boost::system::error_code ec) {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001327 if (ec)
1328 {
1329 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -07001330 messages::internalError(asyncResp->res);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001331 return;
1332 }
1333 BMCWEB_LOG_DEBUG << "Led group update done.";
1334 },
1335 "xyz.openbmc_project.LED.GroupManager",
1336 "/xyz/openbmc_project/led/groups/enclosure_identify",
1337 "org.freedesktop.DBus.Properties", "Set",
1338 "xyz.openbmc_project.Led.Group", "Asserted",
Ed Tanousabf2add2019-01-22 16:40:12 -08001339 std::variant<bool>(
Ed Tanous9712f8a2018-09-21 13:38:49 -07001340 (dbusLedState ==
1341 "xyz.openbmc_project.Led.Physical.Action.Off"
1342 ? false
1343 : true)));
1344 // Update identify led status
1345 BMCWEB_LOG_DEBUG << "Update led SoftwareInventoryCollection.";
1346 crow::connections::systemBus->async_method_call(
1347 [asyncResp{std::move(asyncResp)},
1348 indicatorLed{std::move(*indicatorLed)}](
1349 const boost::system::error_code ec) {
1350 if (ec)
1351 {
1352 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -07001353 messages::internalError(asyncResp->res);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001354 return;
1355 }
1356 BMCWEB_LOG_DEBUG << "Led state update done.";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001357 },
1358 "xyz.openbmc_project.LED.Controller.identify",
1359 "/xyz/openbmc_project/led/physical/identify",
1360 "org.freedesktop.DBus.Properties", "Set",
1361 "xyz.openbmc_project.Led.Physical", "State",
Ed Tanousabf2add2019-01-22 16:40:12 -08001362 std::variant<std::string>(dbusLedState));
Ed Tanous1abe55e2018-09-05 08:30:59 -07001363 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001364 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001365};
Ed Tanous1abe55e2018-09-05 08:30:59 -07001366} // namespace redfish