Remove Redfish Node class
Reduces the total number of lines and will allow for easier testing of
the redfish responses.
A main purpose of the node class was to set app.routeDynamic(). However
now app.routeDynamic can handle the complexity that was once in critical
to node. The macro app.routeDynamic() provides a shorter cleaner
interface to the unerlying app.routeDyanic call. The old pattern set
permissions for 6 interfaces (get, head, patch, put, delete_, and post)
even if only one interface is created. That pattern creates unneeded
code that can be safely removed with no effect.
Unit test for the responses would have to mock the node the class in
order to fully test responses.
see https://github.com/openbmc/bmcweb/issues/181
The following files still need node to be extracted.
virtual_media.hpp
account_service.hpp
redfish_sessions.hpp
ethernet.hpp
The files above use a pattern that is not trivial to address. Often their
responses call an async lambda capturing the inherited class. ie
(https://github.com/openbmc/bmcweb/blob/ffed87b5ad1797ca966d030e7f979770
28d258fa/redfish-core/lib/account_service.hpp#L1393)
At a later point I plan to remove node from the files above.
Tested:
I ran the docker unit test with the following command.
WORKSPACE=$(pwd) UNIT_TEST_PKG=bmcweb
./openbmc-build-scripts/run-unit-test-docker.sh
I ran the validator and this change did not create any issues.
python3 RedfishServiceValidator.py -c config.ini
Signed-off-by: John Edward Broadbent <jebr@google.com>
Signed-off-by: Ed Tanous <edtanous@google.com>
Change-Id: I147a0289c52cb4198345b1ad9bfe6fdddf57f3df
diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
index db58d60..7429b77 100644
--- a/redfish-core/include/redfish.hpp
+++ b/redfish-core/include/redfish.hpp
@@ -67,96 +67,94 @@
nodes.emplace_back(std::make_unique<AccountsCollection>(app));
nodes.emplace_back(std::make_unique<ManagerAccount>(app));
nodes.emplace_back(std::make_unique<SessionCollection>(app));
- nodes.emplace_back(std::make_unique<Roles>(app));
- nodes.emplace_back(std::make_unique<RoleCollection>(app));
- nodes.emplace_back(std::make_unique<ServiceRoot>(app));
- nodes.emplace_back(std::make_unique<NetworkProtocol>(app));
+ requestRoutesRoles(app);
+ requestRoutesRoleCollection(app);
+ requestRoutesServiceRoot(app);
+ requestRoutesNetworkProtocol(app);
nodes.emplace_back(std::make_unique<SessionService>(app));
nodes.emplace_back(std::make_unique<EthernetCollection>(app));
nodes.emplace_back(std::make_unique<EthernetInterface>(app));
- nodes.emplace_back(std::make_unique<Thermal>(app));
- nodes.emplace_back(std::make_unique<ManagerCollection>(app));
- nodes.emplace_back(std::make_unique<Manager>(app));
- nodes.emplace_back(std::make_unique<ManagerResetAction>(app));
- nodes.emplace_back(std::make_unique<ManagerResetActionInfo>(app));
- nodes.emplace_back(std::make_unique<ManagerResetToDefaultsAction>(app));
- nodes.emplace_back(std::make_unique<Power>(app));
- nodes.emplace_back(std::make_unique<ChassisCollection>(app));
- nodes.emplace_back(std::make_unique<Chassis>(app));
- nodes.emplace_back(std::make_unique<ChassisResetAction>(app));
- nodes.emplace_back(std::make_unique<ChassisResetActionInfo>(app));
- nodes.emplace_back(std::make_unique<UpdateService>(app));
- nodes.emplace_back(std::make_unique<StorageCollection>(app));
- nodes.emplace_back(std::make_unique<Storage>(app));
- nodes.emplace_back(std::make_unique<Drive>(app));
+ requestRoutesThermal(app);
+ requestRoutesManagerCollection(app);
+ requestRoutesManager(app);
+ requestRoutesManagerResetAction(app);
+ requestRoutesManagerResetActionInfo(app);
+ requestRoutesManagerResetToDefaultsAction(app);
+ requestRoutesPower(app);
+ requestRoutesChassisCollection(app);
+ requestRoutesChassis(app);
+ requestRoutesChassisResetAction(app);
+ requestRoutesChassisResetActionInfo(app);
+ requestRoutesUpdateService(app);
+ requestRoutesStorageCollection(app);
+ requestRoutesStorage(app);
+ requestRoutesDrive(app);
#ifdef BMCWEB_INSECURE_ENABLE_REDFISH_FW_TFTP_UPDATE
- nodes.emplace_back(
- std::make_unique<UpdateServiceActionsSimpleUpdate>(app));
+ requestRoutesUpdateServiceActionsSimpleUpdate(app);
#endif
- nodes.emplace_back(std::make_unique<SoftwareInventoryCollection>(app));
- nodes.emplace_back(std::make_unique<SoftwareInventory>(app));
+ requestRoutesSoftwareInventoryCollection(app);
+ requestRoutesSoftwareInventory(app);
nodes.emplace_back(
std::make_unique<VlanNetworkInterfaceCollection>(app));
nodes.emplace_back(std::make_unique<VlanNetworkInterface>(app));
- nodes.emplace_back(std::make_unique<SystemLogServiceCollection>(app));
- nodes.emplace_back(std::make_unique<EventLogService>(app));
+ requestRoutesSystemLogServiceCollection(app);
+ requestRoutesEventLogService(app);
- nodes.emplace_back(std::make_unique<PostCodesLogService>(app));
- nodes.emplace_back(std::make_unique<PostCodesClear>(app));
- nodes.emplace_back(std::make_unique<PostCodesEntry>(app));
- nodes.emplace_back(std::make_unique<PostCodesEntryCollection>(app));
+ requestRoutesPostCodesLogService(app);
+ requestRoutesPostCodesClear(app);
+ requestRoutesPostCodesEntry(app);
+ requestRoutesPostCodesEntryCollection(app);
#ifdef BMCWEB_ENABLE_REDFISH_DUMP_LOG
- nodes.emplace_back(std::make_unique<SystemDumpService>(app));
- nodes.emplace_back(std::make_unique<SystemDumpEntryCollection>(app));
- nodes.emplace_back(std::make_unique<SystemDumpEntry>(app));
- nodes.emplace_back(std::make_unique<SystemDumpCreate>(app));
- nodes.emplace_back(std::make_unique<SystemDumpClear>(app));
+ requestRoutesSystemDumpService(app);
+ requestRoutesSystemDumpEntryCollection(app);
+ requestRoutesSystemDumpEntry(app);
+ requestRoutesSystemDumpCreate(app);
+ requestRoutesSystemDumpClear(app);
- nodes.emplace_back(std::make_unique<BMCDumpService>(app));
- nodes.emplace_back(std::make_unique<BMCDumpEntryCollection>(app));
- nodes.emplace_back(std::make_unique<BMCDumpEntry>(app));
- nodes.emplace_back(std::make_unique<BMCDumpCreate>(app));
- nodes.emplace_back(std::make_unique<BMCDumpClear>(app));
+ requestRoutesBMCDumpService(app);
+ requestRoutesBMCDumpEntryCollection(app);
+ requestRoutesBMCDumpEntry(app);
+ requestRoutesBMCDumpCreate(app);
+ requestRoutesBMCDumpClear(app);
#endif
#ifndef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES
- nodes.emplace_back(
- std::make_unique<JournalEventLogEntryCollection>(app));
- nodes.emplace_back(std::make_unique<JournalEventLogEntry>(app));
- nodes.emplace_back(std::make_unique<JournalEventLogClear>(app));
+ requestRoutesJournalEventLogEntryCollection(app);
+ requestRoutesJournalEventLogEntry(app);
+ requestRoutesJournalEventLogClear(app);
#endif
- nodes.emplace_back(std::make_unique<BMCLogServiceCollection>(app));
+ requestRoutesBMCLogServiceCollection(app);
#ifdef BMCWEB_ENABLE_REDFISH_BMC_JOURNAL
- nodes.emplace_back(std::make_unique<BMCJournalLogService>(app));
- nodes.emplace_back(std::make_unique<BMCJournalLogEntryCollection>(app));
- nodes.emplace_back(std::make_unique<BMCJournalLogEntry>(app));
+ requestRoutesBMCJournalLogService(app);
+ requestRoutesBMCJournalLogEntryCollection(app);
+ requestRoutesBMCJournalLogEntry(app);
#endif
#ifdef BMCWEB_ENABLE_REDFISH_CPU_LOG
- nodes.emplace_back(std::make_unique<CrashdumpService>(app));
- nodes.emplace_back(std::make_unique<CrashdumpEntryCollection>(app));
- nodes.emplace_back(std::make_unique<CrashdumpEntry>(app));
- nodes.emplace_back(std::make_unique<CrashdumpFile>(app));
- nodes.emplace_back(std::make_unique<CrashdumpClear>(app));
- nodes.emplace_back(std::make_unique<CrashdumpCollect>(app));
+ requestRoutesCrashdumpService(app);
+ requestRoutesCrashdumpEntryCollection(app);
+ requestRoutesCrashdumpEntry(app);
+ requestRoutesCrashdumpFile(app);
+ requestRoutesCrashdumpClear(app);
+ requestRoutesCrashdumpCollect(app);
#endif // BMCWEB_ENABLE_REDFISH_CPU_LOG
- nodes.emplace_back(std::make_unique<ProcessorCollection>(app));
- nodes.emplace_back(std::make_unique<Processor>(app));
- nodes.emplace_back(std::make_unique<OperatingConfigCollection>(app));
- nodes.emplace_back(std::make_unique<OperatingConfig>(app));
- nodes.emplace_back(std::make_unique<MemoryCollection>(app));
- nodes.emplace_back(std::make_unique<Memory>(app));
+ requestRoutesProcessorCollection(app);
+ requestRoutesProcessor(app);
+ requestRoutesOperatingConfigCollection(app);
+ requestRoutesOperatingConfig(app);
+ requestRoutesMemoryCollection(app);
+ requestRoutesMemory(app);
- nodes.emplace_back(std::make_unique<SystemsCollection>(app));
- nodes.emplace_back(std::make_unique<Systems>(app));
- nodes.emplace_back(std::make_unique<SystemActionsReset>(app));
- nodes.emplace_back(std::make_unique<SystemResetActionInfo>(app));
- nodes.emplace_back(std::make_unique<BiosService>(app));
- nodes.emplace_back(std::make_unique<BiosReset>(app));
+ requestRoutesSystemsCollection(app);
+ requestRoutesSystems(app);
+ requestRoutesSystemActionsReset(app);
+ requestRoutesSystemResetActionInfo(app);
+ requestRoutesBiosService(app);
+ requestRoutesBiosReset(app);
#ifdef BMCWEB_ENABLE_VM_NBDPROXY
nodes.emplace_back(std::make_unique<VirtualMedia>(app));
nodes.emplace_back(std::make_unique<VirtualMediaCollection>(app));
@@ -165,58 +163,51 @@
nodes.emplace_back(std::make_unique<VirtualMediaActionEjectMedia>(app));
#endif // BMCWEB_ENABLE_VM_NBDPROXY
#ifdef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES
- nodes.emplace_back(std::make_unique<DBusLogServiceActionsClear>(app));
- nodes.emplace_back(std::make_unique<DBusEventLogEntryCollection>(app));
- nodes.emplace_back(std::make_unique<DBusEventLogEntry>(app));
- nodes.emplace_back(std::make_unique<DBusEventLogEntryDownload>(app));
+ requestRoutesDBusLogServiceActionsClear(app);
+ requestRoutesDBusEventLogEntryCollection(app);
+ requestRoutesDBusEventLogEntry(app);
+ requestRoutesDBusEventLogEntryDownload(app);
#endif
- nodes.emplace_back(
- std::make_unique<MessageRegistryFileCollection>(app));
- nodes.emplace_back(std::make_unique<MessageRegistryFile>(app));
- nodes.emplace_back(std::make_unique<MessageRegistry>(app));
- nodes.emplace_back(std::make_unique<CertificateService>(app));
- nodes.emplace_back(
- std::make_unique<CertificateActionsReplaceCertificate>(app));
- nodes.emplace_back(std::make_unique<CertificateLocations>(app));
- nodes.emplace_back(std::make_unique<HTTPSCertificateCollection>(app));
- nodes.emplace_back(std::make_unique<HTTPSCertificate>(app));
- nodes.emplace_back(std::make_unique<LDAPCertificateCollection>(app));
- nodes.emplace_back(std::make_unique<LDAPCertificate>(app));
- nodes.emplace_back(std::make_unique<CertificateActionGenerateCSR>(app));
- nodes.emplace_back(
- std::make_unique<TrustStoreCertificateCollection>(app));
- nodes.emplace_back(std::make_unique<TrustStoreCertificate>(app));
- nodes.emplace_back(std::make_unique<SystemPCIeFunctionCollection>(app));
- nodes.emplace_back(std::make_unique<SystemPCIeFunction>(app));
- nodes.emplace_back(std::make_unique<SystemPCIeDeviceCollection>(app));
- nodes.emplace_back(std::make_unique<SystemPCIeDevice>(app));
+ requestRoutesMessageRegistryFileCollection(app);
+ requestRoutesMessageRegistryFile(app);
+ requestRoutesMessageRegistry(app);
- nodes.emplace_back(std::make_unique<SensorCollection>(app));
- nodes.emplace_back(std::make_unique<Sensor>(app));
+ requestRoutesCertificateService(app);
+ requestRoutesCertificateActionGenerateCSR(app);
+ requestRoutesCertificateActionsReplaceCertificate(app);
+ requestRoutesHTTPSCertificate(app);
+ requestRoutesHTTPSCertificateCollection(app);
+ requestRoutesCertificateLocations(app);
+ requestRoutesLDAPCertificateCollection(app);
+ requestRoutesLDAPCertificate(app);
+ requestRoutesTrustStoreCertificateCollection(app);
+ requestRoutesTrustStoreCertificate(app);
- nodes.emplace_back(std::make_unique<TaskMonitor>(app));
- nodes.emplace_back(std::make_unique<TaskService>(app));
- nodes.emplace_back(std::make_unique<TaskCollection>(app));
- nodes.emplace_back(std::make_unique<Task>(app));
- nodes.emplace_back(std::make_unique<EventService>(app));
- nodes.emplace_back(std::make_unique<EventDestinationCollection>(app));
- nodes.emplace_back(std::make_unique<EventDestination>(app));
- nodes.emplace_back(std::make_unique<SubmitTestEvent>(app));
+ requestRoutesSystemPCIeFunctionCollection(app);
+ requestRoutesSystemPCIeFunction(app);
+ requestRoutesSystemPCIeDeviceCollection(app);
+ requestRoutesSystemPCIeDevice(app);
- nodes.emplace_back(
- std::make_unique<HypervisorInterfaceCollection>(app));
- nodes.emplace_back(std::make_unique<HypervisorInterface>(app));
- nodes.emplace_back(std::make_unique<HypervisorSystem>(app));
- nodes.emplace_back(std::make_unique<HypervisorActionsReset>(app));
- nodes.emplace_back(std::make_unique<HypervisorResetActionInfo>(app));
+ requestRoutesSensorCollection(app);
+ requestRoutesSensor(app);
- nodes.emplace_back(std::make_unique<TelemetryService>(app));
- nodes.emplace_back(
- std::make_unique<MetricReportDefinitionCollection>(app));
- nodes.emplace_back(std::make_unique<MetricReportDefinition>(app));
- nodes.emplace_back(std::make_unique<MetricReportCollection>(app));
- nodes.emplace_back(std::make_unique<MetricReport>(app));
+ requestRoutesTaskMonitor(app);
+ requestRoutesTaskService(app);
+ requestRoutesTaskCollection(app);
+ requestRoutesTask(app);
+ requestRoutesEventService(app);
+ requestRoutesEventDestinationCollection(app);
+ requestRoutesEventDestination(app);
+ requestRoutesSubmitTestEvent(app);
+
+ requestRoutesHypervisorSystems(app);
+
+ requestRoutesTelemetryService(app);
+ requestRoutesMetricReportDefinitionCollection(app);
+ requestRoutesMetricReportDefinition(app);
+ requestRoutesMetricReportCollection(app);
+ requestRoutesMetricReport(app);
for (const auto& node : nodes)
{
diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp
index cedea22..2e81104 100644
--- a/redfish-core/lib/account_service.hpp
+++ b/redfish-core/lib/account_service.hpp
@@ -16,6 +16,7 @@
#pragma once
#include "node.hpp"
+#include <app.hpp>
#include <dbus_utility.hpp>
#include <error_messages.hpp>
#include <openbmc_dbus_rest.hpp>
diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp
index 0917cc7..de6f9a1 100644
--- a/redfish-core/lib/bios.hpp
+++ b/redfish-core/lib/bios.hpp
@@ -1,75 +1,62 @@
#pragma once
-#include "node.hpp"
-
+#include <app.hpp>
#include <utils/fw_utils.hpp>
namespace redfish
{
/**
* BiosService class supports handle get method for bios.
*/
-class BiosService : public Node
+inline void requestRoutesBiosService(App& app)
{
- public:
- BiosService(App& app) : Node(app, "/redfish/v1/Systems/system/Bios/")
- {
- entityPrivileges = {{boost::beast::http::verb::get, {{"Login"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Bios/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/Bios";
+ asyncResp->res.jsonValue["@odata.type"] = "#Bios.v1_1_0.Bios";
+ asyncResp->res.jsonValue["Name"] = "BIOS Configuration";
+ asyncResp->res.jsonValue["Description"] =
+ "BIOS Configuration Service";
+ asyncResp->res.jsonValue["Id"] = "BIOS";
+ asyncResp->res.jsonValue["Actions"]["#Bios.ResetBios"] = {
+ {"target",
+ "/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios"}};
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/Bios";
- asyncResp->res.jsonValue["@odata.type"] = "#Bios.v1_1_0.Bios";
- asyncResp->res.jsonValue["Name"] = "BIOS Configuration";
- asyncResp->res.jsonValue["Description"] = "BIOS Configuration Service";
- asyncResp->res.jsonValue["Id"] = "BIOS";
- asyncResp->res.jsonValue["Actions"]["#Bios.ResetBios"] = {
- {"target",
- "/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios"}};
-
- // Get the ActiveSoftwareImage and SoftwareImages
- fw_util::populateFirmwareInformation(asyncResp, fw_util::biosPurpose,
- "", true);
- }
-};
+ // Get the ActiveSoftwareImage and SoftwareImages
+ fw_util::populateFirmwareInformation(
+ asyncResp, fw_util::biosPurpose, "", true);
+ });
+}
/**
* BiosReset class supports handle POST method for Reset bios.
* The class retrieves and sends data directly to D-Bus.
+ *
+ * Function handles POST method request.
+ * Analyzes POST body message before sends Reset request data to D-Bus.
*/
-class BiosReset : public Node
+
+inline void requestRoutesBiosReset(App& app)
{
- public:
- BiosReset(App& app) :
- Node(app, "/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- /**
- * Function handles POST method request.
- * Analyzes POST body message before sends Reset request data to D-Bus.
- */
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "Failed to reset bios: " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
- },
- "org.open_power.Software.Host.Updater",
- "/xyz/openbmc_project/software",
- "xyz.openbmc_project.Common.FactoryReset", "Reset");
- }
-};
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "Failed to reset bios: " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
+ "org.open_power.Software.Host.Updater",
+ "/xyz/openbmc_project/software",
+ "xyz.openbmc_project.Common.FactoryReset", "Reset");
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/certificate_service.hpp b/redfish-core/lib/certificate_service.hpp
index 0e53571..0e26a86 100644
--- a/redfish-core/lib/certificate_service.hpp
+++ b/redfish-core/lib/certificate_service.hpp
@@ -1,7 +1,6 @@
#pragma once
-#include "node.hpp"
-
+#include <app.hpp>
#include <boost/convert.hpp>
#include <boost/convert/strtol.hpp>
@@ -34,47 +33,42 @@
* actions available to manage certificates and links to where certificates
* are installed.
*/
-class CertificateService : public Node
-{
- public:
- CertificateService(App& app) : Node(app, "/redfish/v1/CertificateService/")
- {
- // TODO: Issue#61 No entries are available for Certificate
- // service at https://www.dmtf.org/standards/redfish
- // "redfish standard registries". Need to modify after DMTF
- // publish Privilege details for certificate service
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue = {
- {"@odata.type", "#CertificateService.v1_0_0.CertificateService"},
- {"@odata.id", "/redfish/v1/CertificateService"},
- {"Id", "CertificateService"},
- {"Name", "Certificate Service"},
- {"Description", "Actions available to manage certificates"}};
- asyncResp->res.jsonValue["CertificateLocations"] = {
- {"@odata.id",
- "/redfish/v1/CertificateService/CertificateLocations"}};
- asyncResp->res
- .jsonValue["Actions"]["#CertificateService.ReplaceCertificate"] = {
- {"target", "/redfish/v1/CertificateService/Actions/"
- "CertificateService.ReplaceCertificate"},
- {"CertificateType@Redfish.AllowableValues", {"PEM"}}};
- asyncResp->res.jsonValue["Actions"]["#CertificateService.GenerateCSR"] =
- {{"target", "/redfish/v1/CertificateService/Actions/"
- "CertificateService.GenerateCSR"}};
- }
-}; // CertificateService
+// TODO: Issue#61 No entries are available for Certificate
+// service at https://www.dmtf.org/standards/redfish
+// "redfish standard registries". Need to modify after DMTF
+// publish Privilege details for certificate service
+
+inline void requestRoutesCertificateService(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue = {
+ {"@odata.type",
+ "#CertificateService.v1_0_0.CertificateService"},
+ {"@odata.id", "/redfish/v1/CertificateService"},
+ {"Id", "CertificateService"},
+ {"Name", "Certificate Service"},
+ {"Description",
+ "Actions available to manage certificates"}};
+ asyncResp->res.jsonValue["CertificateLocations"] = {
+ {"@odata.id",
+ "/redfish/v1/CertificateService/CertificateLocations"}};
+ asyncResp->res
+ .jsonValue["Actions"]
+ ["#CertificateService.ReplaceCertificate"] = {
+ {"target", "/redfish/v1/CertificateService/Actions/"
+ "CertificateService.ReplaceCertificate"},
+ {"CertificateType@Redfish.AllowableValues", {"PEM"}}};
+ asyncResp->res
+ .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = {
+ {"target", "/redfish/v1/CertificateService/Actions/"
+ "CertificateService.GenerateCSR"}};
+ });
+} // requestRoutesCertificateService
/**
* @brief Find the ID specified in the URL
@@ -230,259 +224,259 @@
/**
* Action to Generate CSR
*/
-class CertificateActionGenerateCSR : public Node
+inline void requestRoutesCertificateActionGenerateCSR(App& app)
{
- public:
- CertificateActionGenerateCSR(App& app) :
- Node(app, "/redfish/v1/CertificateService/Actions/"
- "CertificateService.GenerateCSR/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/Actions/"
+ "CertificateService.GenerateCSR/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ static const int rsaKeyBitLength = 2048;
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- static const int rsaKeyBitLength = 2048;
+ // Required parameters
+ std::string city;
+ std::string commonName;
+ std::string country;
+ std::string organization;
+ std::string organizationalUnit;
+ std::string state;
+ nlohmann::json certificateCollection;
- // Required parameters
- std::string city;
- std::string commonName;
- std::string country;
- std::string organization;
- std::string organizationalUnit;
- std::string state;
- nlohmann::json certificateCollection;
+ // Optional parameters
+ std::optional<std::vector<std::string>> optAlternativeNames =
+ std::vector<std::string>();
+ std::optional<std::string> optContactPerson = "";
+ std::optional<std::string> optChallengePassword = "";
+ std::optional<std::string> optEmail = "";
+ std::optional<std::string> optGivenName = "";
+ std::optional<std::string> optInitials = "";
+ std::optional<int64_t> optKeyBitLength = rsaKeyBitLength;
+ std::optional<std::string> optKeyCurveId = "secp384r1";
+ std::optional<std::string> optKeyPairAlgorithm = "EC";
+ std::optional<std::vector<std::string>> optKeyUsage =
+ std::vector<std::string>();
+ std::optional<std::string> optSurname = "";
+ std::optional<std::string> optUnstructuredName = "";
+ if (!json_util::readJson(
+ req, asyncResp->res, "City", city, "CommonName",
+ commonName, "ContactPerson", optContactPerson,
+ "Country", country, "Organization", organization,
+ "OrganizationalUnit", organizationalUnit, "State",
+ state, "CertificateCollection", certificateCollection,
+ "AlternativeNames", optAlternativeNames,
+ "ChallengePassword", optChallengePassword, "Email",
+ optEmail, "GivenName", optGivenName, "Initials",
+ optInitials, "KeyBitLength", optKeyBitLength,
+ "KeyCurveId", optKeyCurveId, "KeyPairAlgorithm",
+ optKeyPairAlgorithm, "KeyUsage", optKeyUsage, "Surname",
+ optSurname, "UnstructuredName", optUnstructuredName))
+ {
+ return;
+ }
- // Optional parameters
- std::optional<std::vector<std::string>> optAlternativeNames =
- std::vector<std::string>();
- std::optional<std::string> optContactPerson = "";
- std::optional<std::string> optChallengePassword = "";
- std::optional<std::string> optEmail = "";
- std::optional<std::string> optGivenName = "";
- std::optional<std::string> optInitials = "";
- std::optional<int64_t> optKeyBitLength = rsaKeyBitLength;
- std::optional<std::string> optKeyCurveId = "secp384r1";
- std::optional<std::string> optKeyPairAlgorithm = "EC";
- std::optional<std::vector<std::string>> optKeyUsage =
- std::vector<std::string>();
- std::optional<std::string> optSurname = "";
- std::optional<std::string> optUnstructuredName = "";
- if (!json_util::readJson(
- req, asyncResp->res, "City", city, "CommonName", commonName,
- "ContactPerson", optContactPerson, "Country", country,
- "Organization", organization, "OrganizationalUnit",
- organizationalUnit, "State", state, "CertificateCollection",
- certificateCollection, "AlternativeNames", optAlternativeNames,
- "ChallengePassword", optChallengePassword, "Email", optEmail,
- "GivenName", optGivenName, "Initials", optInitials,
- "KeyBitLength", optKeyBitLength, "KeyCurveId", optKeyCurveId,
- "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage",
- optKeyUsage, "Surname", optSurname, "UnstructuredName",
- optUnstructuredName))
- {
- return;
- }
+ // bmcweb has no way to store or decode a private key challenge
+ // password, which will likely cause bmcweb to crash on startup
+ // if this is not set on a post so not allowing the user to set
+ // value
+ if (*optChallengePassword != "")
+ {
+ messages::actionParameterNotSupported(
+ asyncResp->res, "GenerateCSR", "ChallengePassword");
+ return;
+ }
- // bmcweb has no way to store or decode a private key challenge
- // password, which will likely cause bmcweb to crash on startup if this
- // is not set on a post so not allowing the user to set value
- if (*optChallengePassword != "")
- {
- messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR",
- "ChallengePassword");
- return;
- }
+ std::string certURI;
+ if (!redfish::json_util::readJson(certificateCollection,
+ asyncResp->res, "@odata.id",
+ certURI))
+ {
+ return;
+ }
- std::string certURI;
- if (!redfish::json_util::readJson(certificateCollection, asyncResp->res,
- "@odata.id", certURI))
- {
- return;
- }
+ std::string objectPath;
+ std::string service;
+ if (boost::starts_with(certURI,
+ "/redfish/v1/Managers/bmc/"
+ "NetworkProtocol/HTTPS/Certificates"))
+ {
+ objectPath = certs::httpsObjectPath;
+ service = certs::httpsServiceName;
+ }
+ else if (boost::starts_with(
+ certURI,
+ "/redfish/v1/AccountService/LDAP/Certificates"))
+ {
+ objectPath = certs::ldapObjectPath;
+ service = certs::ldapServiceName;
+ }
+ else
+ {
+ messages::actionParameterNotSupported(
+ asyncResp->res, "CertificateCollection", "GenerateCSR");
+ return;
+ }
- std::string objectPath;
- std::string service;
- if (boost::starts_with(
- certURI,
- "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
- {
- objectPath = certs::httpsObjectPath;
- service = certs::httpsServiceName;
- }
- else if (boost::starts_with(
- certURI, "/redfish/v1/AccountService/LDAP/Certificates"))
- {
- objectPath = certs::ldapObjectPath;
- service = certs::ldapServiceName;
- }
- else
- {
- messages::actionParameterNotSupported(
- asyncResp->res, "CertificateCollection", "GenerateCSR");
- return;
- }
+ // supporting only EC and RSA algorithm
+ if (*optKeyPairAlgorithm != "EC" &&
+ *optKeyPairAlgorithm != "RSA")
+ {
+ messages::actionParameterNotSupported(
+ asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
+ return;
+ }
- // supporting only EC and RSA algorithm
- if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA")
- {
- messages::actionParameterNotSupported(
- asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
- return;
- }
-
- // supporting only 2048 key bit length for RSA algorithm due to time
- // consumed in generating private key
- if (*optKeyPairAlgorithm == "RSA" &&
- *optKeyBitLength != rsaKeyBitLength)
- {
- messages::propertyValueNotInList(asyncResp->res,
- std::to_string(*optKeyBitLength),
- "KeyBitLength");
- return;
- }
-
- // validate KeyUsage supporting only 1 type based on URL
- if (boost::starts_with(
- certURI,
- "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
- {
- if (optKeyUsage->size() == 0)
- {
- optKeyUsage->push_back("ServerAuthentication");
- }
- else if (optKeyUsage->size() == 1)
- {
- if ((*optKeyUsage)[0] != "ServerAuthentication")
+ // supporting only 2048 key bit length for RSA algorithm due to
+ // time consumed in generating private key
+ if (*optKeyPairAlgorithm == "RSA" &&
+ *optKeyBitLength != rsaKeyBitLength)
{
messages::propertyValueNotInList(
- asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
+ asyncResp->res, std::to_string(*optKeyBitLength),
+ "KeyBitLength");
return;
}
- }
- else
- {
- messages::actionParameterNotSupported(
- asyncResp->res, "KeyUsage", "GenerateCSR");
- return;
- }
- }
- else if (boost::starts_with(
- certURI, "/redfish/v1/AccountService/LDAP/Certificates"))
- {
- if (optKeyUsage->size() == 0)
- {
- optKeyUsage->push_back("ClientAuthentication");
- }
- else if (optKeyUsage->size() == 1)
- {
- if ((*optKeyUsage)[0] != "ClientAuthentication")
- {
- messages::propertyValueNotInList(
- asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
- return;
- }
- }
- else
- {
- messages::actionParameterNotSupported(
- asyncResp->res, "KeyUsage", "GenerateCSR");
- return;
- }
- }
- // Only allow one CSR matcher at a time so setting retry time-out and
- // timer expiry to 10 seconds for now.
- static const int timeOut = 10;
- if (csrMatcher)
- {
- messages::serviceTemporarilyUnavailable(asyncResp->res,
- std::to_string(timeOut));
- return;
- }
-
- // Make this static so it survives outside this method
- static boost::asio::steady_timer timeout(*req.ioService);
- timeout.expires_after(std::chrono::seconds(timeOut));
- timeout.async_wait([asyncResp](const boost::system::error_code& ec) {
- csrMatcher = nullptr;
- if (ec)
- {
- // operation_aborted is expected if timer is canceled before
- // completion.
- if (ec != boost::asio::error::operation_aborted)
+ // validate KeyUsage supporting only 1 type based on URL
+ if (boost::starts_with(certURI,
+ "/redfish/v1/Managers/bmc/"
+ "NetworkProtocol/HTTPS/Certificates"))
{
- BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
- }
- return;
- }
- BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR";
- messages::internalError(asyncResp->res);
- });
-
- // create a matcher to wait on CSR object
- BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath;
- std::string match("type='signal',"
- "interface='org.freedesktop.DBus.ObjectManager',"
- "path='" +
- objectPath +
- "',"
- "member='InterfacesAdded'");
- csrMatcher = std::make_unique<sdbusplus::bus::match::match>(
- *crow::connections::systemBus, match,
- [asyncResp, service, objectPath,
- certURI](sdbusplus::message::message& m) {
- timeout.cancel();
- if (m.is_method_error())
- {
- BMCWEB_LOG_ERROR << "Dbus method error!!!";
- messages::internalError(asyncResp->res);
- return;
- }
- std::vector<std::pair<
- std::string, std::vector<std::pair<
- std::string, std::variant<std::string>>>>>
- interfacesProperties;
- sdbusplus::message::object_path csrObjectPath;
- m.read(csrObjectPath, interfacesProperties);
- BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str;
- for (auto& interface : interfacesProperties)
- {
- if (interface.first == "xyz.openbmc_project.Certs.CSR")
+ if (optKeyUsage->size() == 0)
{
- getCSR(asyncResp, certURI, service, objectPath,
- csrObjectPath.str);
- break;
+ optKeyUsage->push_back("ServerAuthentication");
+ }
+ else if (optKeyUsage->size() == 1)
+ {
+ if ((*optKeyUsage)[0] != "ServerAuthentication")
+ {
+ messages::propertyValueNotInList(
+ asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
+ return;
+ }
+ }
+ else
+ {
+ messages::actionParameterNotSupported(
+ asyncResp->res, "KeyUsage", "GenerateCSR");
+ return;
}
}
- });
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code& ec,
- const std::string&) {
- if (ec)
+ else if (boost::starts_with(
+ certURI,
+ "/redfish/v1/AccountService/LDAP/Certificates"))
{
- BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message();
- messages::internalError(asyncResp->res);
+ if (optKeyUsage->size() == 0)
+ {
+ optKeyUsage->push_back("ClientAuthentication");
+ }
+ else if (optKeyUsage->size() == 1)
+ {
+ if ((*optKeyUsage)[0] != "ClientAuthentication")
+ {
+ messages::propertyValueNotInList(
+ asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
+ return;
+ }
+ }
+ else
+ {
+ messages::actionParameterNotSupported(
+ asyncResp->res, "KeyUsage", "GenerateCSR");
+ return;
+ }
+ }
+
+ // Only allow one CSR matcher at a time so setting retry
+ // time-out and timer expiry to 10 seconds for now.
+ static const int timeOut = 10;
+ if (csrMatcher)
+ {
+ messages::serviceTemporarilyUnavailable(
+ asyncResp->res, std::to_string(timeOut));
return;
}
- },
- service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
- "GenerateCSR", *optAlternativeNames, *optChallengePassword, city,
- commonName, *optContactPerson, country, *optEmail, *optGivenName,
- *optInitials, *optKeyBitLength, *optKeyCurveId,
- *optKeyPairAlgorithm, *optKeyUsage, organization,
- organizationalUnit, state, *optSurname, *optUnstructuredName);
- }
-}; // CertificateActionGenerateCSR
+
+ // Make this static so it survives outside this method
+ static boost::asio::steady_timer timeout(*req.ioService);
+ timeout.expires_after(std::chrono::seconds(timeOut));
+ timeout.async_wait([asyncResp](
+ const boost::system::error_code& ec) {
+ csrMatcher = nullptr;
+ if (ec)
+ {
+ // operation_aborted is expected if timer is canceled
+ // before completion.
+ if (ec != boost::asio::error::operation_aborted)
+ {
+ BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
+ }
+ return;
+ }
+ BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR";
+ messages::internalError(asyncResp->res);
+ });
+
+ // create a matcher to wait on CSR object
+ BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath;
+ std::string match(
+ "type='signal',"
+ "interface='org.freedesktop.DBus.ObjectManager',"
+ "path='" +
+ objectPath +
+ "',"
+ "member='InterfacesAdded'");
+ csrMatcher = std::make_unique<sdbusplus::bus::match::match>(
+ *crow::connections::systemBus, match,
+ [asyncResp, service, objectPath,
+ certURI](sdbusplus::message::message& m) {
+ timeout.cancel();
+ if (m.is_method_error())
+ {
+ BMCWEB_LOG_ERROR << "Dbus method error!!!";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ std::vector<std::pair<
+ std::string,
+ std::vector<std::pair<std::string,
+ std::variant<std::string>>>>>
+ interfacesProperties;
+ sdbusplus::message::object_path csrObjectPath;
+ m.read(csrObjectPath, interfacesProperties);
+ BMCWEB_LOG_DEBUG << "CSR object added"
+ << csrObjectPath.str;
+ for (auto& interface : interfacesProperties)
+ {
+ if (interface.first ==
+ "xyz.openbmc_project.Certs.CSR")
+ {
+ getCSR(asyncResp, certURI, service, objectPath,
+ csrObjectPath.str);
+ break;
+ }
+ }
+ });
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code& ec,
+ const std::string&) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "DBUS response error: "
+ << ec.message();
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
+ service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
+ "GenerateCSR", *optAlternativeNames, *optChallengePassword,
+ city, commonName, *optContactPerson, country, *optEmail,
+ *optGivenName, *optInitials, *optKeyBitLength,
+ *optKeyCurveId, *optKeyPairAlgorithm, *optKeyUsage,
+ organization, organizationalUnit, state, *optSurname,
+ *optUnstructuredName);
+ });
+} // requestRoutesCertificateActionGenerateCSR
/**
* @brief Parse and update Certificate Issue/Subject property
@@ -669,713 +663,656 @@
/**
* Action to replace an existing certificate
*/
-class CertificateActionsReplaceCertificate : public Node
+inline void requestRoutesCertificateActionsReplaceCertificate(App& app)
{
- public:
- CertificateActionsReplaceCertificate(App& app) :
- Node(app, "/redfish/v1/CertificateService/Actions/"
- "CertificateService.ReplaceCertificate/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/Actions/"
+ "CertificateService.ReplaceCertificate/")
+ .privileges({"ConfigureComponents"})
+ .methods(
+ boost::beast::http::verb::
+ post)([](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ std::string certificate;
+ nlohmann::json certificateUri;
+ std::optional<std::string> certificateType = "PEM";
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- std::string certificate;
- nlohmann::json certificateUri;
- std::optional<std::string> certificateType = "PEM";
+ if (!json_util::readJson(req, asyncResp->res, "CertificateString",
+ certificate, "CertificateUri",
+ certificateUri, "CertificateType",
+ certificateType))
+ {
+ BMCWEB_LOG_ERROR << "Required parameters are missing";
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (!json_util::readJson(req, asyncResp->res, "CertificateString",
- certificate, "CertificateUri", certificateUri,
- "CertificateType", certificateType))
- {
- BMCWEB_LOG_ERROR << "Required parameters are missing";
- messages::internalError(asyncResp->res);
- return;
- }
+ if (!certificateType)
+ {
+ // should never happen, but it never hurts to be paranoid.
+ return;
+ }
+ if (certificateType != "PEM")
+ {
+ messages::actionParameterNotSupported(
+ asyncResp->res, "CertificateType", "ReplaceCertificate");
+ return;
+ }
- if (!certificateType)
- {
- // should never happen, but it never hurts to be paranoid.
- return;
- }
- if (certificateType != "PEM")
- {
- messages::actionParameterNotSupported(
- asyncResp->res, "CertificateType", "ReplaceCertificate");
- return;
- }
+ std::string certURI;
+ if (!redfish::json_util::readJson(certificateUri, asyncResp->res,
+ "@odata.id", certURI))
+ {
+ messages::actionParameterMissing(
+ asyncResp->res, "ReplaceCertificate", "CertificateUri");
+ return;
+ }
- std::string certURI;
- if (!redfish::json_util::readJson(certificateUri, asyncResp->res,
- "@odata.id", certURI))
- {
- messages::actionParameterMissing(
- asyncResp->res, "ReplaceCertificate", "CertificateUri");
- return;
- }
+ BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI;
+ long id = getIDFromURL(certURI);
+ if (id < 0)
+ {
+ messages::actionParameterValueFormatError(
+ asyncResp->res, certURI, "CertificateUri",
+ "ReplaceCertificate");
+ return;
+ }
+ std::string objectPath;
+ std::string name;
+ std::string service;
+ if (boost::starts_with(certURI,
+ "/redfish/v1/Managers/bmc/NetworkProtocol/"
+ "HTTPS/Certificates/"))
+ {
+ objectPath = std::string(certs::httpsObjectPath) + "/" +
+ std::to_string(id);
+ name = "HTTPS certificate";
+ service = certs::httpsServiceName;
+ }
+ else if (boost::starts_with(
+ certURI,
+ "/redfish/v1/AccountService/LDAP/Certificates/"))
+ {
+ objectPath = std::string(certs::ldapObjectPath) + "/" +
+ std::to_string(id);
+ name = "LDAP certificate";
+ service = certs::ldapServiceName;
+ }
+ else if (boost::starts_with(
+ certURI,
+ "/redfish/v1/Managers/bmc/Truststore/Certificates/"))
+ {
+ objectPath = std::string(certs::authorityObjectPath) + "/" +
+ std::to_string(id);
+ name = "TrustStore certificate";
+ service = certs::authorityServiceName;
+ }
+ else
+ {
+ messages::actionParameterNotSupported(
+ asyncResp->res, "CertificateUri", "ReplaceCertificate");
+ return;
+ }
- BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI;
- long id = getIDFromURL(certURI);
- if (id < 0)
- {
- messages::actionParameterValueFormatError(asyncResp->res, certURI,
- "CertificateUri",
- "ReplaceCertificate");
- return;
- }
- std::string objectPath;
- std::string name;
- std::string service;
- if (boost::starts_with(
- certURI,
- "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"))
- {
- objectPath =
- std::string(certs::httpsObjectPath) + "/" + std::to_string(id);
- name = "HTTPS certificate";
- service = certs::httpsServiceName;
- }
- else if (boost::starts_with(
- certURI, "/redfish/v1/AccountService/LDAP/Certificates/"))
- {
- objectPath =
- std::string(certs::ldapObjectPath) + "/" + std::to_string(id);
- name = "LDAP certificate";
- service = certs::ldapServiceName;
- }
- else if (boost::starts_with(
- certURI,
- "/redfish/v1/Managers/bmc/Truststore/Certificates/"))
- {
- objectPath = std::string(certs::authorityObjectPath) + "/" +
- std::to_string(id);
- name = "TrustStore certificate";
- service = certs::authorityServiceName;
- }
- else
- {
- messages::actionParameterNotSupported(
- asyncResp->res, "CertificateUri", "ReplaceCertificate");
- return;
- }
-
- std::shared_ptr<CertificateFile> certFile =
- std::make_shared<CertificateFile>(certificate);
- crow::connections::systemBus->async_method_call(
- [asyncResp, certFile, objectPath, service, certURI, id,
- name](const boost::system::error_code ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
- messages::resourceNotFound(asyncResp->res, name,
- std::to_string(id));
- return;
- }
- getCertificateProperties(asyncResp, objectPath, service, id,
- certURI, name);
- BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
- << certFile->getCertFilePath();
- },
- service, objectPath, certs::certReplaceIntf, "Replace",
- certFile->getCertFilePath());
- }
-}; // CertificateActionsReplaceCertificate
+ std::shared_ptr<CertificateFile> certFile =
+ std::make_shared<CertificateFile>(certificate);
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, certFile, objectPath, service, certURI, id,
+ name](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
+ messages::resourceNotFound(asyncResp->res, name,
+ std::to_string(id));
+ return;
+ }
+ getCertificateProperties(asyncResp, objectPath, service, id,
+ certURI, name);
+ BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
+ << certFile->getCertFilePath();
+ },
+ service, objectPath, certs::certReplaceIntf, "Replace",
+ certFile->getCertFilePath());
+ });
+} // requestRoutesCertificateActionsReplaceCertificate
/**
* Certificate resource describes a certificate used to prove the identity
* of a component, account or service.
*/
-class HTTPSCertificate : public Node
+
+inline void requestRoutesHTTPSCertificate(App& app)
{
- public:
- HTTPSCertificate(App& app) :
- Node(app,
- "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"
- "<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ BMCWEB_ROUTE(
+ app,
+ "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::
+ get)([](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) -> void {
+ if (param.empty())
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ long id = getIDFromURL(req.url);
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- long id = getIDFromURL(req.url);
-
- BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID=" << std::to_string(id);
- std::string certURL =
- "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" +
- std::to_string(id);
- std::string objectPath = certs::httpsObjectPath;
- objectPath += "/";
- objectPath += std::to_string(id);
- getCertificateProperties(asyncResp, objectPath, certs::httpsServiceName,
- id, certURL, "HTTPS Certificate");
- }
-
-}; // namespace redfish
+ BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID="
+ << std::to_string(id);
+ std::string certURL =
+ "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" +
+ std::to_string(id);
+ std::string objectPath = certs::httpsObjectPath;
+ objectPath += "/";
+ objectPath += std::to_string(id);
+ getCertificateProperties(asyncResp, objectPath,
+ certs::httpsServiceName, id, certURL,
+ "HTTPS Certificate");
+ });
+}
/**
* Collection of HTTPS certificates
*/
-class HTTPSCertificateCollection : public Node
+inline void requestRoutesHTTPSCertificateCollection(App& app)
{
- public:
- HTTPSCertificateCollection(App& app) :
- Node(app,
- "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue = {
- {"@odata.id",
- "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"},
- {"@odata.type", "#CertificateCollection.CertificateCollection"},
- {"Name", "HTTPS Certificates Collection"},
- {"Description", "A Collection of HTTPS certificate instances"}};
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::
+ get)([](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue = {
+ {"@odata.id",
+ "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"},
+ {"@odata.type", "#CertificateCollection.CertificateCollection"},
+ {"Name", "HTTPS Certificates Collection"},
+ {"Description", "A Collection of HTTPS certificate instances"}};
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
- const ManagedObjectType& certs) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
- nlohmann::json& members = asyncResp->res.jsonValue["Members"];
- members = nlohmann::json::array();
- for (const auto& cert : certs)
- {
- long id = getIDFromURL(cert.first.str);
- if (id >= 0)
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec,
+ const ManagedObjectType& certs) {
+ if (ec)
{
- members.push_back(
- {{"@odata.id",
- "/redfish/v1/Managers/bmc/"
- "NetworkProtocol/HTTPS/Certificates/" +
- std::to_string(id)}});
+ BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
+ messages::internalError(asyncResp->res);
+ return;
}
- }
- asyncResp->res.jsonValue["Members@odata.count"] =
- members.size();
- },
- certs::httpsServiceName, certs::httpsObjectPath,
- certs::dbusObjManagerIntf, "GetManagedObjects");
- }
+ nlohmann::json& members =
+ asyncResp->res.jsonValue["Members"];
+ members = nlohmann::json::array();
+ for (const auto& cert : certs)
+ {
+ long id = getIDFromURL(cert.first.str);
+ if (id >= 0)
+ {
+ members.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Managers/bmc/"
+ "NetworkProtocol/HTTPS/Certificates/" +
+ std::to_string(id)}});
+ }
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ members.size();
+ },
+ certs::httpsServiceName, certs::httpsObjectPath,
+ certs::dbusObjManagerIntf, "GetManagedObjects");
+ });
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
- asyncResp->res.jsonValue = {{"Name", "HTTPS Certificate"},
- {"Description", "HTTPS Certificate"}};
+ asyncResp->res.jsonValue = {
+ {"Name", "HTTPS Certificate"},
+ {"Description", "HTTPS Certificate"}};
- std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
+ std::string certFileBody =
+ getCertificateFromReqBody(asyncResp, req);
- if (certFileBody.empty())
- {
- BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
- messages::unrecognizedRequestBody(asyncResp->res);
- return;
- }
-
- std::shared_ptr<CertificateFile> certFile =
- std::make_shared<CertificateFile>(certFileBody);
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, certFile](const boost::system::error_code ec,
- const std::string& objectPath) {
- if (ec)
+ if (certFileBody.empty())
{
- BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
- messages::internalError(asyncResp->res);
+ BMCWEB_LOG_ERROR
+ << "Cannot get certificate from request body.";
+ messages::unrecognizedRequestBody(asyncResp->res);
return;
}
- long certId = getIDFromURL(objectPath);
- if (certId < 0)
+
+ std::shared_ptr<CertificateFile> certFile =
+ std::make_shared<CertificateFile>(certFileBody);
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, certFile](const boost::system::error_code ec,
+ const std::string& objectPath) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ long certId = getIDFromURL(objectPath);
+ if (certId < 0)
+ {
+ BMCWEB_LOG_ERROR << "Invalid objectPath value"
+ << objectPath;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ std::string certURL =
+ "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/"
+ "Certificates/" +
+ std::to_string(certId);
+ getCertificateProperties(
+ asyncResp, objectPath, certs::httpsServiceName,
+ certId, certURL, "HTTPS Certificate");
+ BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
+ << certFile->getCertFilePath();
+ },
+ certs::httpsServiceName, certs::httpsObjectPath,
+ certs::certInstallIntf, "Install",
+ certFile->getCertFilePath());
+ });
+} // requestRoutesHTTPSCertificateCollection
+
+/**
+ * @brief Retrieve the certificates installed list and append to the
+ * response
+ *
+ * @param[in] asyncResp Shared pointer to the response message
+ * @param[in] certURL Path of the certificate object
+ * @param[in] path Path of the D-Bus service object
+ * @return None
+ */
+void getCertificateLocations(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& certURL, const std::string& path,
+ const std::string& service)
+{
+ BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL
+ << " Path=" << path << " service= " << service;
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, certURL](const boost::system::error_code ec,
+ const ManagedObjectType& certs) {
+ if (ec)
+ {
+ BMCWEB_LOG_WARNING
+ << "Certificate collection query failed: " << ec
+ << ", skipping " << certURL;
+ return;
+ }
+ nlohmann::json& links =
+ asyncResp->res.jsonValue["Links"]["Certificates"];
+ for (auto& cert : certs)
+ {
+ long id = getIDFromURL(cert.first.str);
+ if (id >= 0)
{
- BMCWEB_LOG_ERROR << "Invalid objectPath value"
- << objectPath;
- messages::internalError(asyncResp->res);
- return;
+ links.push_back(
+ {{"@odata.id", certURL + std::to_string(id)}});
}
- std::string certURL =
- "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/"
- "Certificates/" +
- std::to_string(certId);
- getCertificateProperties(asyncResp, objectPath,
- certs::httpsServiceName, certId,
- certURL, "HTTPS Certificate");
- BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
- << certFile->getCertFilePath();
- },
- certs::httpsServiceName, certs::httpsObjectPath,
- certs::certInstallIntf, "Install", certFile->getCertFilePath());
- }
-}; // HTTPSCertificateCollection
+ }
+ asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] =
+ links.size();
+ },
+ service, path, certs::dbusObjManagerIntf, "GetManagedObjects");
+}
/**
* The certificate location schema defines a resource that an administrator
* can use in order to locate all certificates installed on a given service.
*/
-class CertificateLocations : public Node
+inline void requestRoutesCertificateLocations(App& app)
{
- public:
- CertificateLocations(App& app) :
- Node(app, "/redfish/v1/CertificateService/CertificateLocations/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::
+ get)([](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue = {
+ {"@odata.id",
+ "/redfish/v1/CertificateService/CertificateLocations"},
+ {"@odata.type",
+ "#CertificateLocations.v1_0_0.CertificateLocations"},
+ {"Name", "Certificate Locations"},
+ {"Id", "CertificateLocations"},
+ {"Description",
+ "Defines a resource that an administrator can use in order to "
+ "locate all certificates installed on a given service"}};
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue = {
- {"@odata.id",
- "/redfish/v1/CertificateService/CertificateLocations"},
- {"@odata.type",
- "#CertificateLocations.v1_0_0.CertificateLocations"},
- {"Name", "Certificate Locations"},
- {"Id", "CertificateLocations"},
- {"Description",
- "Defines a resource that an administrator can use in order to "
- "locate all certificates installed on a given service"}};
-
- nlohmann::json& links =
- asyncResp->res.jsonValue["Links"]["Certificates"];
- links = nlohmann::json::array();
- getCertificateLocations(
- asyncResp,
- "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/",
- certs::httpsObjectPath, certs::httpsServiceName);
- getCertificateLocations(asyncResp,
- "/redfish/v1/AccountService/LDAP/Certificates/",
- certs::ldapObjectPath, certs::ldapServiceName);
- getCertificateLocations(
- asyncResp, "/redfish/v1/Managers/bmc/Truststore/Certificates/",
- certs::authorityObjectPath, certs::authorityServiceName);
- }
- /**
- * @brief Retrieve the certificates installed list and append to the
- * response
- *
- * @param[in] asyncResp Shared pointer to the response message
- * @param[in] certURL Path of the certificate object
- * @param[in] path Path of the D-Bus service object
- * @return None
- */
- void getCertificateLocations(
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& certURL, const std::string& path,
- const std::string& service)
- {
- BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL
- << " Path=" << path << " service= " << service;
- crow::connections::systemBus->async_method_call(
- [asyncResp, certURL](const boost::system::error_code ec,
- const ManagedObjectType& certs) {
- if (ec)
- {
- BMCWEB_LOG_WARNING
- << "Certificate collection query failed: " << ec
- << ", skipping " << certURL;
- return;
- }
- nlohmann::json& links =
- asyncResp->res.jsonValue["Links"]["Certificates"];
- for (auto& cert : certs)
- {
- long id = getIDFromURL(cert.first.str);
- if (id >= 0)
- {
- links.push_back(
- {{"@odata.id", certURL + std::to_string(id)}});
- }
- }
- asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] =
- links.size();
- },
- service, path, certs::dbusObjManagerIntf, "GetManagedObjects");
- }
-}; // CertificateLocations
+ nlohmann::json& links =
+ asyncResp->res.jsonValue["Links"]["Certificates"];
+ links = nlohmann::json::array();
+ getCertificateLocations(
+ asyncResp,
+ "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/",
+ certs::httpsObjectPath, certs::httpsServiceName);
+ getCertificateLocations(
+ asyncResp, "/redfish/v1/AccountService/LDAP/Certificates/",
+ certs::ldapObjectPath, certs::ldapServiceName);
+ getCertificateLocations(
+ asyncResp, "/redfish/v1/Managers/bmc/Truststore/Certificates/",
+ certs::authorityObjectPath, certs::authorityServiceName);
+ });
+}
+// requestRoutesCertificateLocations
/**
* Collection of LDAP certificates
*/
-class LDAPCertificateCollection : public Node
+inline void requestRoutesLDAPCertificateCollection(App& app)
{
- public:
- LDAPCertificateCollection(App& app) :
- Node(app, "/redfish/v1/AccountService/LDAP/Certificates/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue = {
- {"@odata.id", "/redfish/v1/AccountService/LDAP/Certificates"},
- {"@odata.type", "#CertificateCollection.CertificateCollection"},
- {"Name", "LDAP Certificates Collection"},
- {"Description", "A Collection of LDAP certificate instances"}};
+ BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue = {
+ {"@odata.id",
+ "/redfish/v1/AccountService/LDAP/Certificates"},
+ {"@odata.type",
+ "#CertificateCollection.CertificateCollection"},
+ {"Name", "LDAP Certificates Collection"},
+ {"Description",
+ "A Collection of LDAP certificate instances"}};
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
- const ManagedObjectType& certs) {
- nlohmann::json& members = asyncResp->res.jsonValue["Members"];
- nlohmann::json& count =
- asyncResp->res.jsonValue["Members@odata.count"];
- members = nlohmann::json::array();
- count = 0;
- if (ec)
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec,
+ const ManagedObjectType& certs) {
+ nlohmann::json& members =
+ asyncResp->res.jsonValue["Members"];
+ nlohmann::json& count =
+ asyncResp->res.jsonValue["Members@odata.count"];
+ members = nlohmann::json::array();
+ count = 0;
+ if (ec)
+ {
+ BMCWEB_LOG_WARNING
+ << "LDAP certificate query failed: " << ec;
+ return;
+ }
+ for (const auto& cert : certs)
+ {
+ long id = getIDFromURL(cert.first.str);
+ if (id >= 0)
+ {
+ members.push_back(
+ {{"@odata.id", "/redfish/v1/AccountService/"
+ "LDAP/Certificates/" +
+ std::to_string(id)}});
+ }
+ }
+ count = members.size();
+ },
+ certs::ldapServiceName, certs::ldapObjectPath,
+ certs::dbusObjManagerIntf, "GetManagedObjects");
+ });
+
+ BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ std::string certFileBody =
+ getCertificateFromReqBody(asyncResp, req);
+
+ if (certFileBody.empty())
{
- BMCWEB_LOG_WARNING << "LDAP certificate query failed: "
- << ec;
+ BMCWEB_LOG_ERROR
+ << "Cannot get certificate from request body.";
+ messages::unrecognizedRequestBody(asyncResp->res);
return;
}
- for (const auto& cert : certs)
- {
- long id = getIDFromURL(cert.first.str);
- if (id >= 0)
- {
- members.push_back(
- {{"@odata.id", "/redfish/v1/AccountService/"
- "LDAP/Certificates/" +
- std::to_string(id)}});
- }
- }
- count = members.size();
- },
- certs::ldapServiceName, certs::ldapObjectPath,
- certs::dbusObjManagerIntf, "GetManagedObjects");
- }
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
+ std::shared_ptr<CertificateFile> certFile =
+ std::make_shared<CertificateFile>(certFileBody);
- std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
-
- if (certFileBody.empty())
- {
- BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
- messages::unrecognizedRequestBody(asyncResp->res);
- return;
- }
-
- std::shared_ptr<CertificateFile> certFile =
- std::make_shared<CertificateFile>(certFileBody);
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, certFile](const boost::system::error_code ec,
- const std::string& objectPath) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
- long certId = getIDFromURL(objectPath);
- if (certId < 0)
- {
- BMCWEB_LOG_ERROR << "Invalid objectPath value"
- << objectPath;
- messages::internalError(asyncResp->res);
- return;
- }
- std::string certURL =
- "/redfish/v1/AccountService/LDAP/Certificates/" +
- std::to_string(certId);
- getCertificateProperties(asyncResp, objectPath,
- certs::ldapServiceName, certId,
- certURL, "LDAP Certificate");
- BMCWEB_LOG_DEBUG << "LDAP certificate install file="
- << certFile->getCertFilePath();
- },
- certs::ldapServiceName, certs::ldapObjectPath,
- certs::certInstallIntf, "Install", certFile->getCertFilePath());
- }
-}; // LDAPCertificateCollection
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, certFile](const boost::system::error_code ec,
+ const std::string& objectPath) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ long certId = getIDFromURL(objectPath);
+ if (certId < 0)
+ {
+ BMCWEB_LOG_ERROR << "Invalid objectPath value"
+ << objectPath;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ std::string certURL =
+ "/redfish/v1/AccountService/LDAP/Certificates/" +
+ std::to_string(certId);
+ getCertificateProperties(asyncResp, objectPath,
+ certs::ldapServiceName, certId,
+ certURL, "LDAP Certificate");
+ BMCWEB_LOG_DEBUG << "LDAP certificate install file="
+ << certFile->getCertFilePath();
+ },
+ certs::ldapServiceName, certs::ldapObjectPath,
+ certs::certInstallIntf, "Install",
+ certFile->getCertFilePath());
+ });
+} // requestRoutesLDAPCertificateCollection
/**
* Certificate resource describes a certificate used to prove the identity
* of a component, account or service.
*/
-class LDAPCertificate : public Node
+inline void requestRoutesLDAPCertificate(App& app)
{
- public:
- LDAPCertificate(App& app) :
- Node(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
-
- long id = getIDFromURL(req.url);
- if (id < 0)
- {
- BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
- messages::internalError(asyncResp->res);
- return;
- }
- BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << std::to_string(id);
- std::string certURL = "/redfish/v1/AccountService/LDAP/Certificates/" +
- std::to_string(id);
- std::string objectPath = certs::ldapObjectPath;
- objectPath += "/";
- objectPath += std::to_string(id);
- getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName,
- id, certURL, "LDAP Certificate");
- }
-}; // LDAPCertificate
+ BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string&) {
+ long id = getIDFromURL(req.url);
+ if (id < 0)
+ {
+ BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "LDAP Certificate ID="
+ << std::to_string(id);
+ std::string certURL =
+ "/redfish/v1/AccountService/LDAP/Certificates/" +
+ std::to_string(id);
+ std::string objectPath = certs::ldapObjectPath;
+ objectPath += "/";
+ objectPath += std::to_string(id);
+ getCertificateProperties(asyncResp, objectPath,
+ certs::ldapServiceName, id, certURL,
+ "LDAP Certificate");
+ });
+} // requestRoutesLDAPCertificate
/**
* Collection of TrustStoreCertificate certificates
*/
-class TrustStoreCertificateCollection : public Node
+inline void requestRoutesTrustStoreCertificateCollection(App& app)
{
- public:
- TrustStoreCertificateCollection(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue = {
- {"@odata.id", "/redfish/v1/Managers/bmc/Truststore/Certificates/"},
- {"@odata.type", "#CertificateCollection.CertificateCollection"},
- {"Name", "TrustStore Certificates Collection"},
- {"Description",
- "A Collection of TrustStore certificate instances"}};
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue = {
+ {"@odata.id",
+ "/redfish/v1/Managers/bmc/Truststore/Certificates/"},
+ {"@odata.type",
+ "#CertificateCollection.CertificateCollection"},
+ {"Name", "TrustStore Certificates Collection"},
+ {"Description",
+ "A Collection of TrustStore certificate instances"}};
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
- const ManagedObjectType& certs) {
- if (ec)
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec,
+ const ManagedObjectType& certs) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ nlohmann::json& members =
+ asyncResp->res.jsonValue["Members"];
+ members = nlohmann::json::array();
+ for (const auto& cert : certs)
+ {
+ long id = getIDFromURL(cert.first.str);
+ if (id >= 0)
+ {
+ members.push_back(
+ {{"@odata.id", "/redfish/v1/Managers/bmc/"
+ "Truststore/Certificates/" +
+ std::to_string(id)}});
+ }
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ members.size();
+ },
+ certs::authorityServiceName, certs::authorityObjectPath,
+ certs::dbusObjManagerIntf, "GetManagedObjects");
+ });
+
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ std::string certFileBody =
+ getCertificateFromReqBody(asyncResp, req);
+
+ if (certFileBody.empty())
{
- BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
- messages::internalError(asyncResp->res);
+ BMCWEB_LOG_ERROR
+ << "Cannot get certificate from request body.";
+ messages::unrecognizedRequestBody(asyncResp->res);
return;
}
- nlohmann::json& members = asyncResp->res.jsonValue["Members"];
- members = nlohmann::json::array();
- for (const auto& cert : certs)
- {
- long id = getIDFromURL(cert.first.str);
- if (id >= 0)
- {
- members.push_back(
- {{"@odata.id", "/redfish/v1/Managers/bmc/"
- "Truststore/Certificates/" +
- std::to_string(id)}});
- }
- }
- asyncResp->res.jsonValue["Members@odata.count"] =
- members.size();
- },
- certs::authorityServiceName, certs::authorityObjectPath,
- certs::dbusObjManagerIntf, "GetManagedObjects");
- }
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
+ std::shared_ptr<CertificateFile> certFile =
+ std::make_shared<CertificateFile>(certFileBody);
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, certFile](const boost::system::error_code ec,
+ const std::string& objectPath) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ long certId = getIDFromURL(objectPath);
+ if (certId < 0)
+ {
+ BMCWEB_LOG_ERROR << "Invalid objectPath value"
+ << objectPath;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ std::string certURL = "/redfish/v1/Managers/bmc/"
+ "Truststore/Certificates/" +
+ std::to_string(certId);
- std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
-
- if (certFileBody.empty())
- {
- BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
- messages::unrecognizedRequestBody(asyncResp->res);
- return;
- }
-
- std::shared_ptr<CertificateFile> certFile =
- std::make_shared<CertificateFile>(certFileBody);
- crow::connections::systemBus->async_method_call(
- [asyncResp, certFile](const boost::system::error_code ec,
- const std::string& objectPath) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
- long certId = getIDFromURL(objectPath);
- if (certId < 0)
- {
- BMCWEB_LOG_ERROR << "Invalid objectPath value"
- << objectPath;
- messages::internalError(asyncResp->res);
- return;
- }
- std::string certURL = "/redfish/v1/Managers/bmc/"
- "Truststore/Certificates/" +
- std::to_string(certId);
-
- getCertificateProperties(asyncResp, objectPath,
- certs::authorityServiceName, certId,
- certURL, "TrustStore Certificate");
- BMCWEB_LOG_DEBUG << "TrustStore certificate install file="
- << certFile->getCertFilePath();
- },
- certs::authorityServiceName, certs::authorityObjectPath,
- certs::certInstallIntf, "Install", certFile->getCertFilePath());
- }
-}; // TrustStoreCertificateCollection
+ getCertificateProperties(
+ asyncResp, objectPath, certs::authorityServiceName,
+ certId, certURL, "TrustStore Certificate");
+ BMCWEB_LOG_DEBUG
+ << "TrustStore certificate install file="
+ << certFile->getCertFilePath();
+ },
+ certs::authorityServiceName, certs::authorityObjectPath,
+ certs::certInstallIntf, "Install",
+ certFile->getCertFilePath());
+ });
+} // requestRoutesTrustStoreCertificateCollection
/**
* Certificate resource describes a certificate used to prove the identity
* of a component, account or service.
*/
-class TrustStoreCertificate : public Node
+inline void requestRoutesTrustStoreCertificate(App& app)
{
- public:
- TrustStoreCertificate(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
-
- long id = getIDFromURL(req.url);
- if (id < 0)
- {
- BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
- messages::internalError(asyncResp->res);
- return;
- }
- BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doGet ID="
- << std::to_string(id);
- std::string certURL =
- "/redfish/v1/Managers/bmc/Truststore/Certificates/" +
- std::to_string(id);
- std::string objectPath = certs::authorityObjectPath;
- objectPath += "/";
- objectPath += std::to_string(id);
- getCertificateProperties(asyncResp, objectPath,
- certs::authorityServiceName, id, certURL,
- "TrustStore Certificate");
- }
-
- void doDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- long id = getIDFromURL(req.url);
- if (id < 0)
- {
- BMCWEB_LOG_ERROR << "Invalid url value: " << req.url;
- messages::resourceNotFound(asyncResp->res, "TrustStore Certificate",
- std::string(req.url));
- return;
- }
- BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doDelete ID="
- << std::to_string(id);
- std::string certPath = certs::authorityObjectPath;
- certPath += "/";
- certPath += std::to_string(id);
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, id](const boost::system::error_code ec) {
- if (ec)
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
+ .privileges({"Loign"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string&) {
+ long id = getIDFromURL(req.url);
+ if (id < 0)
{
- messages::resourceNotFound(asyncResp->res,
- "TrustStore Certificate",
- std::to_string(id));
+ BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
+ messages::internalError(asyncResp->res);
return;
}
- BMCWEB_LOG_INFO << "Certificate deleted";
- asyncResp->res.result(boost::beast::http::status::no_content);
- },
- certs::authorityServiceName, certPath, certs::objDeleteIntf,
- "Delete");
- }
-}; // TrustStoreCertificate
+ BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doGet ID="
+ << std::to_string(id);
+ std::string certURL =
+ "/redfish/v1/Managers/bmc/Truststore/Certificates/" +
+ std::to_string(id);
+ std::string objectPath = certs::authorityObjectPath;
+ objectPath += "/";
+ objectPath += std::to_string(id);
+ getCertificateProperties(asyncResp, objectPath,
+ certs::authorityServiceName, id,
+ certURL, "TrustStore Certificate");
+ });
+
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::delete_)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ if (param.empty())
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ long id = getIDFromURL(req.url);
+ if (id < 0)
+ {
+ BMCWEB_LOG_ERROR << "Invalid url value: " << req.url;
+ messages::resourceNotFound(asyncResp->res,
+ "TrustStore Certificate",
+ std::string(req.url));
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doDelete ID="
+ << std::to_string(id);
+ std::string certPath = certs::authorityObjectPath;
+ certPath += "/";
+ certPath += std::to_string(id);
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, id](const boost::system::error_code ec) {
+ if (ec)
+ {
+ messages::resourceNotFound(asyncResp->res,
+ "TrustStore Certificate",
+ std::to_string(id));
+ return;
+ }
+ BMCWEB_LOG_INFO << "Certificate deleted";
+ asyncResp->res.result(
+ boost::beast::http::status::no_content);
+ },
+ certs::authorityServiceName, certPath, certs::objDeleteIntf,
+ "Delete");
+ });
+} // requestRoutesTrustStoreCertificate
} // namespace redfish
diff --git a/redfish-core/lib/chassis.hpp b/redfish-core/lib/chassis.hpp
index e96a678..22fa0cc 100644
--- a/redfish-core/lib/chassis.hpp
+++ b/redfish-core/lib/chassis.hpp
@@ -17,8 +17,8 @@
#include "health.hpp"
#include "led.hpp"
-#include "node.hpp"
+#include <app.hpp>
#include <boost/container/flat_map.hpp>
#include <utils/collection.hpp>
@@ -157,398 +157,382 @@
/**
* ChassisCollection derived class for delivering Chassis Collection Schema
+ * Functions triggers appropriate requests on DBus
*/
-class ChassisCollection : public Node
+inline void requestRoutesChassisCollection(App& app)
{
- public:
- ChassisCollection(App& app) : Node(app, "/redfish/v1/Chassis/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#ChassisCollection.ChassisCollection";
+ asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
+ asyncResp->res.jsonValue["Name"] = "Chassis Collection";
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.type"] =
- "#ChassisCollection.ChassisCollection";
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
- asyncResp->res.jsonValue["Name"] = "Chassis Collection";
-
- collection_util::getCollectionMembers(
- asyncResp, "/redfish/v1/Chassis",
- {"xyz.openbmc_project.Inventory.Item.Board",
- "xyz.openbmc_project.Inventory.Item.Chassis"});
- }
-};
+ collection_util::getCollectionMembers(
+ asyncResp, "/redfish/v1/Chassis",
+ {"xyz.openbmc_project.Inventory.Item.Board",
+ "xyz.openbmc_project.Inventory.Item.Chassis"});
+ });
+}
/**
* Chassis override class for delivering Chassis Schema
+ * Functions triggers appropriate requests on DBus
*/
-class Chassis : public Node
+inline void requestRoutesChassis(App& app)
{
- public:
- Chassis(App& app) : Node(app, "/redfish/v1/Chassis/<str>/", std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::get)([](const crow::Request&,
+ const std::shared_ptr<
+ bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId) {
+ const std::array<const char*, 2> interfaces = {
+ "xyz.openbmc_project.Inventory.Item.Board",
+ "xyz.openbmc_project.Inventory.Item.Chassis"};
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- const std::array<const char*, 2> interfaces = {
- "xyz.openbmc_project.Inventory.Item.Board",
- "xyz.openbmc_project.Inventory.Item.Chassis"};
-
- // Check if there is required param, truly entering this shall be
- // impossible.
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& chassisId = params[0];
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, chassisId(std::string(chassisId))](
- const boost::system::error_code ec,
- const crow::openbmc_mapper::GetSubTreeType& subtree) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- // Iterate over all retrieved ObjectPaths.
- for (const std::pair<
- std::string,
- std::vector<
- std::pair<std::string, std::vector<std::string>>>>&
- object : subtree)
- {
- const std::string& path = object.first;
- const std::vector<
- std::pair<std::string, std::vector<std::string>>>&
- connectionNames = object.second;
- sdbusplus::message::object_path objPath(path);
- if (objPath.filename() != chassisId)
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, chassisId(std::string(chassisId))](
+ const boost::system::error_code ec,
+ const crow::openbmc_mapper::GetSubTreeType& subtree) {
+ if (ec)
{
- continue;
+ messages::internalError(asyncResp->res);
+ return;
}
-
- auto health = std::make_shared<HealthPopulate>(asyncResp);
-
- crow::connections::systemBus->async_method_call(
- [health](const boost::system::error_code ec2,
- std::variant<std::vector<std::string>>& resp) {
- if (ec2)
- {
- return; // no sensors = no failures
- }
- std::vector<std::string>* data =
- std::get_if<std::vector<std::string>>(&resp);
- if (data == nullptr)
- {
- return;
- }
- health->inventory = std::move(*data);
- },
- "xyz.openbmc_project.ObjectMapper",
- path + "/all_sensors",
- "org.freedesktop.DBus.Properties", "Get",
- "xyz.openbmc_project.Association", "endpoints");
-
- health->populate();
-
- if (connectionNames.size() < 1)
+ // Iterate over all retrieved ObjectPaths.
+ for (const std::pair<
+ std::string,
+ std::vector<std::pair<std::string,
+ std::vector<std::string>>>>&
+ object : subtree)
{
- BMCWEB_LOG_ERROR << "Got 0 Connection names";
- continue;
- }
+ const std::string& path = object.first;
+ const std::vector<
+ std::pair<std::string, std::vector<std::string>>>&
+ connectionNames = object.second;
- asyncResp->res.jsonValue["@odata.type"] =
- "#Chassis.v1_14_0.Chassis";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Chassis/" + chassisId;
- asyncResp->res.jsonValue["Name"] = "Chassis Collection";
- asyncResp->res.jsonValue["ChassisType"] = "RackMount";
- asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] = {
- {"target", "/redfish/v1/Chassis/" + chassisId +
- "/Actions/Chassis.Reset"},
- {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
- chassisId +
- "/ResetActionInfo"}};
- asyncResp->res.jsonValue["PCIeDevices"] = {
- {"@odata.id",
- "/redfish/v1/Systems/system/PCIeDevices"}};
-
- const std::string& connectionName =
- connectionNames[0].first;
-
- const std::vector<std::string>& interfaces2 =
- connectionNames[0].second;
- const std::array<const char*, 2> hasIndicatorLed = {
- "xyz.openbmc_project.Inventory.Item.Panel",
- "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
-
- for (const char* interface : hasIndicatorLed)
- {
- if (std::find(interfaces2.begin(), interfaces2.end(),
- interface) != interfaces2.end())
+ if (!boost::ends_with(path, chassisId))
{
- getIndicatorLedState(asyncResp);
- getLocationIndicatorActive(asyncResp);
- break;
+ continue;
}
- }
- const std::string locationInterface =
- "xyz.openbmc_project.Inventory.Decorator.LocationCode";
- if (std::find(interfaces2.begin(), interfaces2.end(),
- locationInterface) != interfaces2.end())
- {
+ auto health =
+ std::make_shared<HealthPopulate>(asyncResp);
+
+ crow::connections::systemBus->async_method_call(
+ [health](
+ const boost::system::error_code ec2,
+ std::variant<std::vector<std::string>>& resp) {
+ if (ec2)
+ {
+ return; // no sensors = no failures
+ }
+ std::vector<std::string>* data =
+ std::get_if<std::vector<std::string>>(
+ &resp);
+ if (data == nullptr)
+ {
+ return;
+ }
+ health->inventory = std::move(*data);
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ path + "/all_sensors",
+ "org.freedesktop.DBus.Properties", "Get",
+ "xyz.openbmc_project.Association", "endpoints");
+
+ health->populate();
+
+ if (connectionNames.size() < 1)
+ {
+ BMCWEB_LOG_ERROR << "Got 0 Connection names";
+ continue;
+ }
+
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#Chassis.v1_14_0.Chassis";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Chassis/" + chassisId;
+ asyncResp->res.jsonValue["Name"] = "Chassis Collection";
+ asyncResp->res.jsonValue["ChassisType"] = "RackMount";
+ asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] =
+ {{"target", "/redfish/v1/Chassis/" + chassisId +
+ "/Actions/Chassis.Reset"},
+ {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
+ chassisId +
+ "/ResetActionInfo"}};
+ asyncResp->res.jsonValue["PCIeDevices"] = {
+ {"@odata.id",
+ "/redfish/v1/Systems/system/PCIeDevices"}};
+
+ const std::string& connectionName =
+ connectionNames[0].first;
+
+ const std::vector<std::string>& interfaces2 =
+ connectionNames[0].second;
+ const std::array<const char*, 2> hasIndicatorLed = {
+ "xyz.openbmc_project.Inventory.Item.Panel",
+ "xyz.openbmc_project.Inventory.Item.Board."
+ "Motherboard"};
+
+ for (const char* interface : hasIndicatorLed)
+ {
+ if (std::find(interfaces2.begin(),
+ interfaces2.end(),
+ interface) != interfaces2.end())
+ {
+ getIndicatorLedState(asyncResp);
+ getLocationIndicatorActive(asyncResp);
+ break;
+ }
+ }
+
+ const std::string locationInterface =
+ "xyz.openbmc_project.Inventory.Decorator."
+ "LocationCode";
+ if (std::find(interfaces2.begin(), interfaces2.end(),
+ locationInterface) != interfaces2.end())
+ {
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, chassisId(std::string(chassisId))](
+ const boost::system::error_code ec,
+ const std::variant<std::string>& property) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG
+ << "DBUS response error for "
+ "Location";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ const std::string* value =
+ std::get_if<std::string>(&property);
+ if (value == nullptr)
+ {
+ BMCWEB_LOG_DEBUG
+ << "Null value returned "
+ "for locaton code";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res
+ .jsonValue["Location"]["PartLocation"]
+ ["ServiceLabel"] = *value;
+ },
+ connectionName, path,
+ "org.freedesktop.DBus.Properties", "Get",
+ locationInterface, "LocationCode");
+ }
+
crow::connections::systemBus->async_method_call(
[asyncResp, chassisId(std::string(chassisId))](
- const boost::system::error_code ec,
- const std::variant<std::string>& property) {
- if (ec)
+ const boost::system::error_code /*ec2*/,
+ const std::vector<
+ std::pair<std::string, VariantType>>&
+ propertiesList) {
+ for (const std::pair<std::string, VariantType>&
+ property : propertiesList)
{
- BMCWEB_LOG_DEBUG
- << "DBUS response error for Location";
- messages::internalError(asyncResp->res);
- return;
- }
-
- const std::string* value =
- std::get_if<std::string>(&property);
- if (value == nullptr)
- {
- BMCWEB_LOG_DEBUG << "Null value returned "
- "for locaton code";
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res
- .jsonValue["Location"]["PartLocation"]
- ["ServiceLabel"] = *value;
- },
- connectionName, path,
- "org.freedesktop.DBus.Properties", "Get",
- locationInterface, "LocationCode");
- }
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, chassisId(std::string(chassisId))](
- const boost::system::error_code /*ec2*/,
- const std::vector<std::pair<
- std::string, VariantType>>& propertiesList) {
- for (const std::pair<std::string, VariantType>&
- property : propertiesList)
- {
- // Store DBus properties that are also Redfish
- // properties with same name and a string value
- const std::string& propertyName =
- property.first;
- if ((propertyName == "PartNumber") ||
- (propertyName == "SerialNumber") ||
- (propertyName == "Manufacturer") ||
- (propertyName == "Model"))
- {
- const std::string* value =
- std::get_if<std::string>(
- &property.second);
- if (value != nullptr)
+ // Store DBus properties that are also
+ // Redfish properties with same name and a
+ // string value
+ const std::string& propertyName =
+ property.first;
+ if ((propertyName == "PartNumber") ||
+ (propertyName == "SerialNumber") ||
+ (propertyName == "Manufacturer") ||
+ (propertyName == "Model"))
{
- asyncResp->res.jsonValue[propertyName] =
- *value;
+ const std::string* value =
+ std::get_if<std::string>(
+ &property.second);
+ if (value != nullptr)
+ {
+ asyncResp->res
+ .jsonValue[propertyName] =
+ *value;
+ }
}
}
+ asyncResp->res.jsonValue["Name"] = chassisId;
+ asyncResp->res.jsonValue["Id"] = chassisId;
+ asyncResp->res.jsonValue["Thermal"] = {
+ {"@odata.id", "/redfish/v1/Chassis/" +
+ chassisId + "/Thermal"}};
+ // Power object
+ asyncResp->res.jsonValue["Power"] = {
+ {"@odata.id", "/redfish/v1/Chassis/" +
+ chassisId + "/Power"}};
+ // SensorCollection
+ asyncResp->res.jsonValue["Sensors"] = {
+ {"@odata.id", "/redfish/v1/Chassis/" +
+ chassisId + "/Sensors"}};
+ asyncResp->res.jsonValue["Status"] = {
+ {"State", "Enabled"},
+ };
+
+ asyncResp->res
+ .jsonValue["Links"]["ComputerSystems"] = {
+ {{"@odata.id",
+ "/redfish/v1/Systems/system"}}};
+ asyncResp->res.jsonValue["Links"]["ManagedBy"] =
+ {{{"@odata.id",
+ "/redfish/v1/Managers/bmc"}}};
+ getChassisState(asyncResp);
+ },
+ connectionName, path,
+ "org.freedesktop.DBus.Properties", "GetAll",
+ "xyz.openbmc_project.Inventory.Decorator.Asset");
+ return;
+ }
+
+ // Couldn't find an object with that name. return an error
+ messages::resourceNotFound(
+ asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/inventory", 0, interfaces);
+
+ getPhysicalSecurityData(asyncResp);
+ });
+
+ BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
+ .privileges({"ConfigureComponents"})
+ .methods(
+ boost::beast::http::verb::
+ patch)([](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ std::optional<bool> locationIndicatorActive;
+ std::optional<std::string> indicatorLed;
+
+ if (param.empty())
+ {
+ return;
+ }
+
+ if (!json_util::readJson(
+ req, asyncResp->res, "LocationIndicatorActive",
+ locationIndicatorActive, "IndicatorLED", indicatorLed))
+ {
+ return;
+ }
+
+ // TODO (Gunnar): Remove IndicatorLED after enough time has passed
+ if (!locationIndicatorActive && !indicatorLed)
+ {
+ return; // delete this when we support more patch properties
+ }
+ if (indicatorLed)
+ {
+ asyncResp->res.addHeader(
+ boost::beast::http::field::warning,
+ "299 - \"IndicatorLED is deprecated. Use "
+ "LocationIndicatorActive instead.\"");
+ }
+
+ const std::array<const char*, 2> interfaces = {
+ "xyz.openbmc_project.Inventory.Item.Board",
+ "xyz.openbmc_project.Inventory.Item.Chassis"};
+
+ const std::string& chassisId = param;
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
+ const boost::system::error_code ec,
+ const crow::openbmc_mapper::GetSubTreeType& subtree) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ // Iterate over all retrieved ObjectPaths.
+ for (const std::pair<
+ std::string,
+ std::vector<std::pair<std::string,
+ std::vector<std::string>>>>&
+ object : subtree)
+ {
+ const std::string& path = object.first;
+ const std::vector<
+ std::pair<std::string, std::vector<std::string>>>&
+ connectionNames = object.second;
+
+ if (!boost::ends_with(path, chassisId))
+ {
+ continue;
+ }
+
+ if (connectionNames.size() < 1)
+ {
+ BMCWEB_LOG_ERROR << "Got 0 Connection names";
+ continue;
+ }
+
+ const std::vector<std::string>& interfaces3 =
+ connectionNames[0].second;
+
+ const std::array<const char*, 2> hasIndicatorLed = {
+ "xyz.openbmc_project.Inventory.Item.Panel",
+ "xyz.openbmc_project.Inventory.Item.Board."
+ "Motherboard"};
+ bool indicatorChassis = false;
+ for (const char* interface : hasIndicatorLed)
+ {
+ if (std::find(interfaces3.begin(),
+ interfaces3.end(),
+ interface) != interfaces3.end())
+ {
+ indicatorChassis = true;
+ break;
}
- asyncResp->res.jsonValue["Name"] = chassisId;
- asyncResp->res.jsonValue["Id"] = chassisId;
- asyncResp->res.jsonValue["Thermal"] = {
- {"@odata.id", "/redfish/v1/Chassis/" +
- chassisId + "/Thermal"}};
- // Power object
- asyncResp->res.jsonValue["Power"] = {
- {"@odata.id", "/redfish/v1/Chassis/" +
- chassisId + "/Power"}};
- // SensorCollection
- asyncResp->res.jsonValue["Sensors"] = {
- {"@odata.id", "/redfish/v1/Chassis/" +
- chassisId + "/Sensors"}};
- asyncResp->res.jsonValue["Status"] = {
- {"State", "Enabled"},
- };
-
- asyncResp->res
- .jsonValue["Links"]["ComputerSystems"] = {
- {{"@odata.id", "/redfish/v1/Systems/system"}}};
- asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
- {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
- getChassisState(asyncResp);
- },
- connectionName, path, "org.freedesktop.DBus.Properties",
- "GetAll",
- "xyz.openbmc_project.Inventory.Decorator.Asset");
- return;
- }
-
- // Couldn't find an object with that name. return an error
- messages::resourceNotFound(
- asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTree",
- "/xyz/openbmc_project/inventory", 0, interfaces);
-
- getPhysicalSecurityData(asyncResp);
- }
-
- void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>& params) override
- {
- std::optional<bool> locationIndicatorActive;
- std::optional<std::string> indicatorLed;
-
- if (params.size() != 1)
- {
- return;
- }
-
- if (!json_util::readJson(req, asyncResp->res, "LocationIndicatorActive",
- locationIndicatorActive, "IndicatorLED",
- indicatorLed))
- {
- return;
- }
-
- // TODO (Gunnar): Remove IndicatorLED after enough time has passed
- if (!locationIndicatorActive && !indicatorLed)
- {
- return; // delete this when we support more patch properties
- }
- if (indicatorLed)
- {
- asyncResp->res.addHeader(boost::beast::http::field::warning,
- "299 - \"IndicatorLED is deprecated. Use "
- "LocationIndicatorActive instead.\"");
- }
-
- const std::array<const char*, 2> interfaces = {
- "xyz.openbmc_project.Inventory.Item.Board",
- "xyz.openbmc_project.Inventory.Item.Chassis"};
-
- const std::string& chassisId = params[0];
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
- const boost::system::error_code ec,
- const crow::openbmc_mapper::GetSubTreeType& subtree) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- // Iterate over all retrieved ObjectPaths.
- for (const std::pair<
- std::string,
- std::vector<
- std::pair<std::string, std::vector<std::string>>>>&
- object : subtree)
- {
- const std::string& path = object.first;
- const std::vector<
- std::pair<std::string, std::vector<std::string>>>&
- connectionNames = object.second;
-
- if (!boost::ends_with(path, chassisId))
- {
- continue;
+ }
+ if (locationIndicatorActive)
+ {
+ if (indicatorChassis)
+ {
+ setLocationIndicatorActive(
+ asyncResp, *locationIndicatorActive);
+ }
+ else
+ {
+ messages::propertyUnknown(
+ asyncResp->res, "LocationIndicatorActive");
+ }
+ }
+ if (indicatorLed)
+ {
+ if (indicatorChassis)
+ {
+ setIndicatorLedState(asyncResp, *indicatorLed);
+ }
+ else
+ {
+ messages::propertyUnknown(asyncResp->res,
+ "IndicatorLED");
+ }
+ }
+ return;
}
- if (connectionNames.size() < 1)
- {
- BMCWEB_LOG_ERROR << "Got 0 Connection names";
- continue;
- }
-
- const std::vector<std::string>& interfaces3 =
- connectionNames[0].second;
-
- const std::array<const char*, 2> hasIndicatorLed = {
- "xyz.openbmc_project.Inventory.Item.Panel",
- "xyz.openbmc_project.Inventory.Item.Board."
- "Motherboard"};
- bool indicatorChassis = false;
- for (const char* interface : hasIndicatorLed)
- {
- if (std::find(interfaces3.begin(), interfaces3.end(),
- interface) != interfaces3.end())
- {
- indicatorChassis = true;
- break;
- }
- }
- if (locationIndicatorActive)
- {
- if (indicatorChassis)
- {
- setLocationIndicatorActive(
- asyncResp, *locationIndicatorActive);
- }
- else
- {
- messages::propertyUnknown(
- asyncResp->res, "LocationIndicatorActive");
- }
- }
- if (indicatorLed)
- {
- if (indicatorChassis)
- {
- setIndicatorLedState(asyncResp, *indicatorLed);
- }
- else
- {
- messages::propertyUnknown(asyncResp->res,
- "IndicatorLED");
- }
- }
- return;
- }
-
- messages::resourceNotFound(
- asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTree",
- "/xyz/openbmc_project/inventory", 0, interfaces);
- }
-};
+ messages::resourceNotFound(
+ asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/inventory", 0, interfaces);
+ });
+}
inline void
doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
@@ -613,98 +597,67 @@
/**
* ChassisResetAction class supports the POST method for the Reset
* action.
+ * Function handles POST method request.
+ * Analyzes POST body before sending Reset request data to D-Bus.
*/
-class ChassisResetAction : public Node
+
+inline void requestRoutesChassisResetAction(App& app)
{
- public:
- ChassisResetAction(App& app) :
- Node(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string&) {
+ BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
- private:
- /**
- * Function handles POST method request.
- * Analyzes POST body before sending Reset request data to D-Bus.
- */
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
+ std::string resetType;
- std::string resetType;
+ if (!json_util::readJson(req, asyncResp->res, "ResetType",
+ resetType))
+ {
+ return;
+ }
- if (!json_util::readJson(req, asyncResp->res, "ResetType", resetType))
- {
- return;
- }
+ if (resetType != "PowerCycle")
+ {
+ BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
+ << resetType;
+ messages::actionParameterNotSupported(
+ asyncResp->res, resetType, "ResetType");
- if (resetType != "PowerCycle")
- {
- BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
- << resetType;
- messages::actionParameterNotSupported(asyncResp->res, resetType,
- "ResetType");
-
- return;
- }
- doChassisPowerCycle(asyncResp);
- }
-};
+ return;
+ }
+ doChassisPowerCycle(asyncResp);
+ });
+}
/**
* ChassisResetActionInfo derived class for delivering Chassis
* ResetType AllowableValues using ResetInfo schema.
*/
-class ChassisResetActionInfo : public Node
+inline void requestRoutesChassisResetActionInfo(App& app)
{
- public:
- /*
- * Default Constructor
- */
- ChassisResetActionInfo(App& app) :
- Node(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/", std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId)
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& chassisId = params[0];
-
- asyncResp->res.jsonValue = {
- {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
- {"@odata.id",
- "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"},
- {"Name", "Reset Action Info"},
- {"Id", "ResetActionInfo"},
- {"Parameters",
- {{{"Name", "ResetType"},
- {"Required", true},
- {"DataType", "String"},
- {"AllowableValues", {"PowerCycle"}}}}}};
- }
-};
+ {
+ asyncResp->res.jsonValue = {
+ {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
+ {"@odata.id",
+ "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"},
+ {"Name", "Reset Action Info"},
+ {"Id", "ResetActionInfo"},
+ {"Parameters",
+ {{{"Name", "ResetType"},
+ {"Required", true},
+ {"DataType", "String"},
+ {"AllowableValues", {"PowerCycle"}}}}}};
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp
index 3e10599..99f452d 100644
--- a/redfish-core/lib/ethernet.hpp
+++ b/redfish-core/lib/ethernet.hpp
@@ -15,6 +15,7 @@
*/
#pragma once
+#include <app.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
#include <dbus_singleton.hpp>
diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
index 64a2009..367b6a2 100644
--- a/redfish-core/lib/event_service.hpp
+++ b/redfish-core/lib/event_service.hpp
@@ -16,6 +16,7 @@
#pragma once
#include "event_service_manager.hpp"
+#include <app.hpp>
namespace redfish
{
@@ -36,612 +37,572 @@
static constexpr const uint8_t maxNoOfSubscriptions = 20;
-class EventService : public Node
+inline void requestRoutesEventService(App& app)
{
- public:
- EventService(App& app) : Node(app, "/redfish/v1/EventService/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue = {
+ {"@odata.type", "#EventService.v1_5_0.EventService"},
+ {"Id", "EventService"},
+ {"Name", "Event Service"},
+ {"Subscriptions",
+ {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}},
+ {"Actions",
+ {{"#EventService.SubmitTestEvent",
+ {{"target", "/redfish/v1/EventService/Actions/"
+ "EventService.SubmitTestEvent"}}}}},
+ {"@odata.id", "/redfish/v1/EventService"}};
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
+ const auto& [enabled, retryAttempts, retryTimeoutInterval] =
+ EventServiceManager::getInstance().getEventServiceConfig();
- asyncResp->res.jsonValue = {
- {"@odata.type", "#EventService.v1_5_0.EventService"},
- {"Id", "EventService"},
- {"Name", "Event Service"},
- {"Subscriptions",
- {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}},
- {"Actions",
- {{"#EventService.SubmitTestEvent",
- {{"target", "/redfish/v1/EventService/Actions/"
- "EventService.SubmitTestEvent"}}}}},
- {"@odata.id", "/redfish/v1/EventService"}};
+ asyncResp->res.jsonValue["Status"]["State"] =
+ (enabled ? "Enabled" : "Disabled");
+ asyncResp->res.jsonValue["ServiceEnabled"] = enabled;
+ asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
+ retryAttempts;
+ asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
+ retryTimeoutInterval;
+ asyncResp->res.jsonValue["EventFormatTypes"] =
+ supportedEvtFormatTypes;
+ asyncResp->res.jsonValue["RegistryPrefixes"] =
+ supportedRegPrefixes;
+ asyncResp->res.jsonValue["ResourceTypes"] =
+ supportedResourceTypes;
- const auto& [enabled, retryAttempts, retryTimeoutInterval] =
- EventServiceManager::getInstance().getEventServiceConfig();
+ nlohmann::json supportedSSEFilters = {
+ {"EventFormatType", true}, {"MessageId", true},
+ {"MetricReportDefinition", true}, {"RegistryPrefix", true},
+ {"OriginResource", false}, {"ResourceType", false}};
- asyncResp->res.jsonValue["Status"]["State"] =
- (enabled ? "Enabled" : "Disabled");
- asyncResp->res.jsonValue["ServiceEnabled"] = enabled;
- asyncResp->res.jsonValue["DeliveryRetryAttempts"] = retryAttempts;
- asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
- retryTimeoutInterval;
- asyncResp->res.jsonValue["EventFormatTypes"] = supportedEvtFormatTypes;
- asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
- asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
+ asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
+ supportedSSEFilters;
+ });
- nlohmann::json supportedSSEFilters = {
- {"EventFormatType", true}, {"MessageId", true},
- {"MetricReportDefinition", true}, {"RegistryPrefix", true},
- {"OriginResource", false}, {"ResourceType", false}};
+ BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::patch)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
- asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
- supportedSSEFilters;
- }
-
- void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
-
- std::optional<bool> serviceEnabled;
- std::optional<uint32_t> retryAttemps;
- std::optional<uint32_t> retryInterval;
-
- if (!json_util::readJson(req, asyncResp->res, "ServiceEnabled",
- serviceEnabled, "DeliveryRetryAttempts",
- retryAttemps, "DeliveryRetryIntervalSeconds",
- retryInterval))
- {
- return;
- }
-
- auto [enabled, retryCount, retryTimeoutInterval] =
- EventServiceManager::getInstance().getEventServiceConfig();
-
- if (serviceEnabled)
- {
- enabled = *serviceEnabled;
- }
-
- if (retryAttemps)
- {
- // Supported range [1-3]
- if ((*retryAttemps < 1) || (*retryAttemps > 3))
{
- messages::queryParameterOutOfRange(
- asyncResp->res, std::to_string(*retryAttemps),
- "DeliveryRetryAttempts", "[1-3]");
- }
- else
- {
- retryCount = *retryAttemps;
- }
- }
+ std::optional<bool> serviceEnabled;
+ std::optional<uint32_t> retryAttemps;
+ std::optional<uint32_t> retryInterval;
- if (retryInterval)
- {
- // Supported range [30 - 180]
- if ((*retryInterval < 30) || (*retryInterval > 180))
- {
- messages::queryParameterOutOfRange(
- asyncResp->res, std::to_string(*retryInterval),
- "DeliveryRetryIntervalSeconds", "[30-180]");
- }
- else
- {
- retryTimeoutInterval = *retryInterval;
- }
- }
-
- EventServiceManager::getInstance().setEventServiceConfig(
- std::make_tuple(enabled, retryCount, retryTimeoutInterval));
- }
-};
-
-class SubmitTestEvent : public Node
-{
- public:
- SubmitTestEvent(App& app) :
- Node(app,
- "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- EventServiceManager::getInstance().sendTestEventLog();
- asyncResp->res.result(boost::beast::http::status::no_content);
- }
-};
-
-class EventDestinationCollection : public Node
-{
- public:
- EventDestinationCollection(App& app) :
- Node(app, "/redfish/v1/EventService/Subscriptions/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- asyncResp->res.jsonValue = {
- {"@odata.type",
- "#EventDestinationCollection.EventDestinationCollection"},
- {"@odata.id", "/redfish/v1/EventService/Subscriptions"},
- {"Name", "Event Destination Collections"}};
-
- nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
-
- std::vector<std::string> subscripIds =
- EventServiceManager::getInstance().getAllIDs();
- memberArray = nlohmann::json::array();
- asyncResp->res.jsonValue["Members@odata.count"] = subscripIds.size();
-
- for (const std::string& id : subscripIds)
- {
- memberArray.push_back(
- {{"@odata.id",
- "/redfish/v1/EventService/Subscriptions/" + id}});
- }
- }
-
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
-
- if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
- maxNoOfSubscriptions)
- {
- messages::eventSubscriptionLimitExceeded(asyncResp->res);
- return;
- }
- std::string destUrl;
- std::string protocol;
- std::optional<std::string> context;
- std::optional<std::string> subscriptionType;
- std::optional<std::string> eventFormatType2;
- std::optional<std::string> retryPolicy;
- std::optional<std::vector<std::string>> msgIds;
- std::optional<std::vector<std::string>> regPrefixes;
- std::optional<std::vector<std::string>> resTypes;
- std::optional<std::vector<nlohmann::json>> headers;
- std::optional<std::vector<nlohmann::json>> mrdJsonArray;
-
- if (!json_util::readJson(
- req, asyncResp->res, "Destination", destUrl, "Context", context,
- "Protocol", protocol, "SubscriptionType", subscriptionType,
- "EventFormatType", eventFormatType2, "HttpHeaders", headers,
- "RegistryPrefixes", regPrefixes, "MessageIds", msgIds,
- "DeliveryRetryPolicy", retryPolicy, "MetricReportDefinitions",
- mrdJsonArray, "ResourceTypes", resTypes))
- {
- return;
- }
-
- if (regPrefixes && msgIds)
- {
- if (regPrefixes->size() && msgIds->size())
- {
- messages::mutualExclusiveProperties(
- asyncResp->res, "RegistryPrefixes", "MessageIds");
- return;
- }
- }
-
- // Validate the URL using regex expression
- // Format: <protocol>://<host>:<port>/<uri>
- // protocol: http/https
- // host: Exclude ' ', ':', '#', '?'
- // port: Empty or numeric value with ':' separator.
- // uri: Start with '/' and Exclude '#', ' '
- // Can include query params(ex: '/event?test=1')
- // TODO: Need to validate hostname extensively(as per rfc)
- const std::regex urlRegex(
- "(http|https)://([^/\\x20\\x3f\\x23\\x3a]+):?([0-9]*)(/"
- "([^\\x20\\x23\\x3f]*\\x3f?([^\\x20\\x23\\x3f])*)?)");
- std::cmatch match;
- if (!std::regex_match(destUrl.c_str(), match, urlRegex))
- {
- messages::propertyValueFormatError(asyncResp->res, destUrl,
- "Destination");
- return;
- }
-
- std::string uriProto = std::string(match[1].first, match[1].second);
- if (uriProto == "http")
- {
-#ifndef BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING
- messages::propertyValueFormatError(asyncResp->res, destUrl,
- "Destination");
- return;
-#endif
- }
-
- std::string host = std::string(match[2].first, match[2].second);
- std::string port = std::string(match[3].first, match[3].second);
- std::string path = std::string(match[4].first, match[4].second);
- if (port.empty())
- {
- if (uriProto == "http")
- {
- port = "80";
- }
- else
- {
- port = "443";
- }
- }
- if (path.empty())
- {
- path = "/";
- }
-
- std::shared_ptr<Subscription> subValue =
- std::make_shared<Subscription>(host, port, path, uriProto);
-
- subValue->destinationUrl = destUrl;
-
- if (subscriptionType)
- {
- if (*subscriptionType != "RedfishEvent")
- {
- messages::propertyValueNotInList(
- asyncResp->res, *subscriptionType, "SubscriptionType");
- return;
- }
- subValue->subscriptionType = *subscriptionType;
- }
- else
- {
- subValue->subscriptionType = "RedfishEvent"; // Default
- }
-
- if (protocol != "Redfish")
- {
- messages::propertyValueNotInList(asyncResp->res, protocol,
- "Protocol");
- return;
- }
- subValue->protocol = protocol;
-
- if (eventFormatType2)
- {
- if (std::find(supportedEvtFormatTypes.begin(),
- supportedEvtFormatTypes.end(),
- *eventFormatType2) == supportedEvtFormatTypes.end())
- {
- messages::propertyValueNotInList(
- asyncResp->res, *eventFormatType2, "EventFormatType");
- return;
- }
- subValue->eventFormatType = *eventFormatType2;
- }
- else
- {
- // If not specified, use default "Event"
- subValue->eventFormatType = "Event";
- }
-
- if (context)
- {
- subValue->customText = *context;
- }
-
- if (headers)
- {
- subValue->httpHeaders = *headers;
- }
-
- if (regPrefixes)
- {
- for (const std::string& it : *regPrefixes)
- {
- if (std::find(supportedRegPrefixes.begin(),
- supportedRegPrefixes.end(),
- it) == supportedRegPrefixes.end())
+ if (!json_util::readJson(
+ req, asyncResp->res, "ServiceEnabled", serviceEnabled,
+ "DeliveryRetryAttempts", retryAttemps,
+ "DeliveryRetryIntervalSeconds", retryInterval))
{
- messages::propertyValueNotInList(asyncResp->res, it,
- "RegistryPrefixes");
return;
}
- }
- subValue->registryPrefixes = *regPrefixes;
- }
- if (resTypes)
- {
- for (const std::string& it : *resTypes)
- {
- if (std::find(supportedResourceTypes.begin(),
- supportedResourceTypes.end(),
- it) == supportedResourceTypes.end())
+ auto [enabled, retryCount, retryTimeoutInterval] =
+ EventServiceManager::getInstance().getEventServiceConfig();
+
+ if (serviceEnabled)
{
- messages::propertyValueNotInList(asyncResp->res, it,
- "ResourceTypes");
- return;
+ enabled = *serviceEnabled;
}
- }
- subValue->resourceTypes = *resTypes;
- }
- if (msgIds)
- {
- std::vector<std::string> registryPrefix;
-
- // If no registry prefixes are mentioned, consider all supported
- // prefixes
- if (subValue->registryPrefixes.empty())
- {
- registryPrefix.assign(supportedRegPrefixes.begin(),
- supportedRegPrefixes.end());
- }
- else
- {
- registryPrefix = subValue->registryPrefixes;
- }
-
- for (const std::string& id : *msgIds)
- {
- bool validId = false;
-
- // Check for Message ID in each of the selected Registry
- for (const std::string& it : registryPrefix)
+ if (retryAttemps)
{
- const boost::beast::span<
- const redfish::message_registries::MessageEntry>
- registry =
- redfish::message_registries::getRegistryFromPrefix(
- it);
-
- if (std::any_of(
- registry.cbegin(), registry.cend(),
- [&id](
- const redfish::message_registries::MessageEntry&
- messageEntry) {
- return !id.compare(messageEntry.first);
- }))
+ // Supported range [1-3]
+ if ((*retryAttemps < 1) || (*retryAttemps > 3))
{
- validId = true;
- break;
+ messages::queryParameterOutOfRange(
+ asyncResp->res, std::to_string(*retryAttemps),
+ "DeliveryRetryAttempts", "[1-3]");
+ }
+ else
+ {
+ retryCount = *retryAttemps;
}
}
- if (!validId)
+ if (retryInterval)
{
- messages::propertyValueNotInList(asyncResp->res, id,
- "MessageIds");
+ // Supported range [30 - 180]
+ if ((*retryInterval < 30) || (*retryInterval > 180))
+ {
+ messages::queryParameterOutOfRange(
+ asyncResp->res, std::to_string(*retryInterval),
+ "DeliveryRetryIntervalSeconds", "[30-180]");
+ }
+ else
+ {
+ retryTimeoutInterval = *retryInterval;
+ }
+ }
+
+ EventServiceManager::getInstance().setEventServiceConfig(
+ std::make_tuple(enabled, retryCount, retryTimeoutInterval));
+ });
+}
+
+inline void requestRoutesSubmitTestEvent(App& app)
+{
+
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ EventServiceManager::getInstance().sendTestEventLog();
+ asyncResp->res.result(boost::beast::http::status::no_content);
+ });
+}
+
+inline void requestRoutesEventDestinationCollection(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue = {
+ {"@odata.type",
+ "#EventDestinationCollection.EventDestinationCollection"},
+ {"@odata.id", "/redfish/v1/EventService/Subscriptions"},
+ {"Name", "Event Destination Collections"}};
+
+ nlohmann::json& memberArray =
+ asyncResp->res.jsonValue["Members"];
+
+ std::vector<std::string> subscripIds =
+ EventServiceManager::getInstance().getAllIDs();
+ memberArray = nlohmann::json::array();
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ subscripIds.size();
+
+ for (const std::string& id : subscripIds)
+ {
+ memberArray.push_back(
+ {{"@odata.id",
+ "/redfish/v1/EventService/Subscriptions/" + id}});
+ }
+ });
+ BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ if (EventServiceManager::getInstance()
+ .getNumberOfSubscriptions() >= maxNoOfSubscriptions)
+ {
+ messages::eventSubscriptionLimitExceeded(asyncResp->res);
return;
}
- }
+ std::string destUrl;
+ std::string protocol;
+ std::optional<std::string> context;
+ std::optional<std::string> subscriptionType;
+ std::optional<std::string> eventFormatType2;
+ std::optional<std::string> retryPolicy;
+ std::optional<std::vector<std::string>> msgIds;
+ std::optional<std::vector<std::string>> regPrefixes;
+ std::optional<std::vector<std::string>> resTypes;
+ std::optional<std::vector<nlohmann::json>> headers;
+ std::optional<std::vector<nlohmann::json>> mrdJsonArray;
- subValue->registryMsgIds = *msgIds;
- }
-
- if (retryPolicy)
- {
- if (std::find(supportedRetryPolicies.begin(),
- supportedRetryPolicies.end(),
- *retryPolicy) == supportedRetryPolicies.end())
- {
- messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
- "DeliveryRetryPolicy");
- return;
- }
- subValue->retryPolicy = *retryPolicy;
- }
- else
- {
- // Default "TerminateAfterRetries"
- subValue->retryPolicy = "TerminateAfterRetries";
- }
-
- if (mrdJsonArray)
- {
- for (nlohmann::json& mrdObj : *mrdJsonArray)
- {
- std::string mrdUri;
- if (json_util::getValueFromJsonObject(mrdObj, "@odata.id",
- mrdUri))
+ if (!json_util::readJson(
+ req, asyncResp->res, "Destination", destUrl, "Context",
+ context, "Protocol", protocol, "SubscriptionType",
+ subscriptionType, "EventFormatType", eventFormatType2,
+ "HttpHeaders", headers, "RegistryPrefixes", regPrefixes,
+ "MessageIds", msgIds, "DeliveryRetryPolicy",
+ retryPolicy, "MetricReportDefinitions", mrdJsonArray,
+ "ResourceTypes", resTypes))
{
- subValue->metricReportDefinitions.emplace_back(mrdUri);
+ return;
+ }
+
+ if (regPrefixes && msgIds)
+ {
+ if (regPrefixes->size() && msgIds->size())
+ {
+ messages::mutualExclusiveProperties(
+ asyncResp->res, "RegistryPrefixes", "MessageIds");
+ return;
+ }
+ }
+
+ // Validate the URL using regex expression
+ // Format: <protocol>://<host>:<port>/<uri>
+ // protocol: http/https
+ // host: Exclude ' ', ':', '#', '?'
+ // port: Empty or numeric value with ':' separator.
+ // uri: Start with '/' and Exclude '#', ' '
+ // Can include query params(ex: '/event?test=1')
+ // TODO: Need to validate hostname extensively(as per rfc)
+ const std::regex urlRegex(
+ "(http|https)://([^/\\x20\\x3f\\x23\\x3a]+):?([0-9]*)(/"
+ "([^\\x20\\x23\\x3f]*\\x3f?([^\\x20\\x23\\x3f])*)?)");
+ std::cmatch match;
+ if (!std::regex_match(destUrl.c_str(), match, urlRegex))
+ {
+ messages::propertyValueFormatError(asyncResp->res, destUrl,
+ "Destination");
+ return;
+ }
+
+ std::string uriProto =
+ std::string(match[1].first, match[1].second);
+ if (uriProto == "http")
+ {
+#ifndef BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING
+ messages::propertyValueFormatError(asyncResp->res, destUrl,
+ "Destination");
+ return;
+#endif
+ }
+
+ std::string host = std::string(match[2].first, match[2].second);
+ std::string port = std::string(match[3].first, match[3].second);
+ std::string path = std::string(match[4].first, match[4].second);
+ if (port.empty())
+ {
+ if (uriProto == "http")
+ {
+ port = "80";
+ }
+ else
+ {
+ port = "443";
+ }
+ }
+ if (path.empty())
+ {
+ path = "/";
+ }
+
+ std::shared_ptr<Subscription> subValue =
+ std::make_shared<Subscription>(host, port, path, uriProto);
+
+ subValue->destinationUrl = destUrl;
+
+ if (subscriptionType)
+ {
+ if (*subscriptionType != "RedfishEvent")
+ {
+ messages::propertyValueNotInList(asyncResp->res,
+ *subscriptionType,
+ "SubscriptionType");
+ return;
+ }
+ subValue->subscriptionType = *subscriptionType;
}
else
{
- messages::propertyValueFormatError(
- asyncResp->res,
- mrdObj.dump(2, ' ', true,
- nlohmann::json::error_handler_t::replace),
- "MetricReportDefinitions");
+ subValue->subscriptionType = "RedfishEvent"; // Default
+ }
+
+ if (protocol != "Redfish")
+ {
+ messages::propertyValueNotInList(asyncResp->res, protocol,
+ "Protocol");
return;
}
- }
- }
+ subValue->protocol = protocol;
- std::string id =
- EventServiceManager::getInstance().addSubscription(subValue);
- if (id.empty())
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (eventFormatType2)
+ {
+ if (std::find(supportedEvtFormatTypes.begin(),
+ supportedEvtFormatTypes.end(),
+ *eventFormatType2) ==
+ supportedEvtFormatTypes.end())
+ {
+ messages::propertyValueNotInList(asyncResp->res,
+ *eventFormatType2,
+ "EventFormatType");
+ return;
+ }
+ subValue->eventFormatType = *eventFormatType2;
+ }
+ else
+ {
+ // If not specified, use default "Event"
+ subValue->eventFormatType = "Event";
+ }
- messages::created(asyncResp->res);
- asyncResp->res.addHeader(
- "Location", "/redfish/v1/EventService/Subscriptions/" + id);
- }
-};
+ if (context)
+ {
+ subValue->customText = *context;
+ }
-class EventDestination : public Node
+ if (headers)
+ {
+ subValue->httpHeaders = *headers;
+ }
+
+ if (regPrefixes)
+ {
+ for (const std::string& it : *regPrefixes)
+ {
+ if (std::find(supportedRegPrefixes.begin(),
+ supportedRegPrefixes.end(),
+ it) == supportedRegPrefixes.end())
+ {
+ messages::propertyValueNotInList(
+ asyncResp->res, it, "RegistryPrefixes");
+ return;
+ }
+ }
+ subValue->registryPrefixes = *regPrefixes;
+ }
+
+ if (resTypes)
+ {
+ for (const std::string& it : *resTypes)
+ {
+ if (std::find(supportedResourceTypes.begin(),
+ supportedResourceTypes.end(),
+ it) == supportedResourceTypes.end())
+ {
+ messages::propertyValueNotInList(asyncResp->res, it,
+ "ResourceTypes");
+ return;
+ }
+ }
+ subValue->resourceTypes = *resTypes;
+ }
+
+ if (msgIds)
+ {
+ std::vector<std::string> registryPrefix;
+
+ // If no registry prefixes are mentioned, consider all
+ // supported prefixes
+ if (subValue->registryPrefixes.empty())
+ {
+ registryPrefix.assign(supportedRegPrefixes.begin(),
+ supportedRegPrefixes.end());
+ }
+ else
+ {
+ registryPrefix = subValue->registryPrefixes;
+ }
+
+ for (const std::string& id : *msgIds)
+ {
+ bool validId = false;
+
+ // Check for Message ID in each of the selected Registry
+ for (const std::string& it : registryPrefix)
+ {
+ const boost::beast::span<
+ const redfish::message_registries::MessageEntry>
+ registry = redfish::message_registries::
+ getRegistryFromPrefix(it);
+
+ if (std::any_of(
+ registry.cbegin(), registry.cend(),
+ [&id](const redfish::message_registries::
+ MessageEntry& messageEntry) {
+ return !id.compare(messageEntry.first);
+ }))
+ {
+ validId = true;
+ break;
+ }
+ }
+
+ if (!validId)
+ {
+ messages::propertyValueNotInList(asyncResp->res, id,
+ "MessageIds");
+ return;
+ }
+ }
+
+ subValue->registryMsgIds = *msgIds;
+ }
+
+ if (retryPolicy)
+ {
+ if (std::find(supportedRetryPolicies.begin(),
+ supportedRetryPolicies.end(),
+ *retryPolicy) == supportedRetryPolicies.end())
+ {
+ messages::propertyValueNotInList(asyncResp->res,
+ *retryPolicy,
+ "DeliveryRetryPolicy");
+ return;
+ }
+ subValue->retryPolicy = *retryPolicy;
+ }
+ else
+ {
+ // Default "TerminateAfterRetries"
+ subValue->retryPolicy = "TerminateAfterRetries";
+ }
+
+ if (mrdJsonArray)
+ {
+ for (nlohmann::json& mrdObj : *mrdJsonArray)
+ {
+ std::string mrdUri;
+ if (json_util::getValueFromJsonObject(
+ mrdObj, "@odata.id", mrdUri))
+ {
+ subValue->metricReportDefinitions.emplace_back(
+ mrdUri);
+ }
+ else
+ {
+ messages::propertyValueFormatError(
+ asyncResp->res,
+ mrdObj.dump(
+ 2, ' ', true,
+ nlohmann::json::error_handler_t::replace),
+ "MetricReportDefinitions");
+ return;
+ }
+ }
+ }
+
+ std::string id =
+ EventServiceManager::getInstance().addSubscription(
+ subValue);
+ if (id.empty())
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ messages::created(asyncResp->res);
+ asyncResp->res.addHeader(
+ "Location", "/redfish/v1/EventService/Subscriptions/" + id);
+ });
+}
+
+inline void requestRoutesEventDestination(App& app)
{
- public:
- EventDestination(App& app) :
- Node(app, "/redfish/v1/EventService/Subscriptions/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "redfish/v1/EventService/Subscriptions/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ std::shared_ptr<Subscription> subValue =
+ EventServiceManager::getInstance().getSubscription(param);
+ if (subValue == nullptr)
+ {
+ asyncResp->res.result(
+ boost::beast::http::status::not_found);
+ return;
+ }
+ const std::string& id = param;
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
+ asyncResp->res.jsonValue = {
+ {"@odata.type",
+ "#EventDestination.v1_7_0.EventDestination"},
+ {"Protocol", "Redfish"}};
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/EventService/Subscriptions/" + id;
+ asyncResp->res.jsonValue["Id"] = id;
+ asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
+ asyncResp->res.jsonValue["Destination"] =
+ subValue->destinationUrl;
+ asyncResp->res.jsonValue["Context"] = subValue->customText;
+ asyncResp->res.jsonValue["SubscriptionType"] =
+ subValue->subscriptionType;
+ asyncResp->res.jsonValue["HttpHeaders"] = subValue->httpHeaders;
+ asyncResp->res.jsonValue["EventFormatType"] =
+ subValue->eventFormatType;
+ asyncResp->res.jsonValue["RegistryPrefixes"] =
+ subValue->registryPrefixes;
+ asyncResp->res.jsonValue["ResourceTypes"] =
+ subValue->resourceTypes;
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ asyncResp->res.jsonValue["MessageIds"] =
+ subValue->registryMsgIds;
+ asyncResp->res.jsonValue["DeliveryRetryPolicy"] =
+ subValue->retryPolicy;
- std::shared_ptr<Subscription> subValue =
- EventServiceManager::getInstance().getSubscription(params[0]);
- if (subValue == nullptr)
- {
- asyncResp->res.result(boost::beast::http::status::not_found);
- return;
- }
- const std::string& id = params[0];
+ std::vector<nlohmann::json> mrdJsonArray;
+ for (const auto& mdrUri : subValue->metricReportDefinitions)
+ {
+ mrdJsonArray.push_back({{"@odata.id", mdrUri}});
+ }
+ asyncResp->res.jsonValue["MetricReportDefinitions"] =
+ mrdJsonArray;
+ });
+ /////redfish/v1/EventService/Subscriptions/
+ // ConfigureManager
+ BMCWEB_ROUTE(app, "redfish/v1/EventService/Subscriptions/<str>/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::patch)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ std::shared_ptr<Subscription> subValue =
+ EventServiceManager::getInstance().getSubscription(param);
+ if (subValue == nullptr)
+ {
+ asyncResp->res.result(
+ boost::beast::http::status::not_found);
+ return;
+ }
- asyncResp->res.jsonValue = {
- {"@odata.type", "#EventDestination.v1_7_0.EventDestination"},
- {"Protocol", "Redfish"}};
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/EventService/Subscriptions/" + id;
- asyncResp->res.jsonValue["Id"] = id;
- asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
- asyncResp->res.jsonValue["Destination"] = subValue->destinationUrl;
- asyncResp->res.jsonValue["Context"] = subValue->customText;
- asyncResp->res.jsonValue["SubscriptionType"] =
- subValue->subscriptionType;
- asyncResp->res.jsonValue["HttpHeaders"] = subValue->httpHeaders;
- asyncResp->res.jsonValue["EventFormatType"] = subValue->eventFormatType;
- asyncResp->res.jsonValue["RegistryPrefixes"] =
- subValue->registryPrefixes;
- asyncResp->res.jsonValue["ResourceTypes"] = subValue->resourceTypes;
+ std::optional<std::string> context;
+ std::optional<std::string> retryPolicy;
+ std::optional<std::vector<nlohmann::json>> headers;
- asyncResp->res.jsonValue["MessageIds"] = subValue->registryMsgIds;
- asyncResp->res.jsonValue["DeliveryRetryPolicy"] = subValue->retryPolicy;
+ if (!json_util::readJson(req, asyncResp->res, "Context",
+ context, "DeliveryRetryPolicy",
+ retryPolicy, "HttpHeaders", headers))
+ {
+ return;
+ }
- std::vector<nlohmann::json> mrdJsonArray;
- for (const auto& mdrUri : subValue->metricReportDefinitions)
- {
- mrdJsonArray.push_back({{"@odata.id", mdrUri}});
- }
- asyncResp->res.jsonValue["MetricReportDefinitions"] = mrdJsonArray;
- }
+ if (context)
+ {
+ subValue->customText = *context;
+ }
- void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>& params) override
- {
+ if (headers)
+ {
+ subValue->httpHeaders = *headers;
+ }
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (retryPolicy)
+ {
+ if (std::find(supportedRetryPolicies.begin(),
+ supportedRetryPolicies.end(),
+ *retryPolicy) == supportedRetryPolicies.end())
+ {
+ messages::propertyValueNotInList(asyncResp->res,
+ *retryPolicy,
+ "DeliveryRetryPolicy");
+ return;
+ }
+ subValue->retryPolicy = *retryPolicy;
+ subValue->updateRetryPolicy();
+ }
- std::shared_ptr<Subscription> subValue =
- EventServiceManager::getInstance().getSubscription(params[0]);
- if (subValue == nullptr)
- {
- asyncResp->res.result(boost::beast::http::status::not_found);
- return;
- }
-
- std::optional<std::string> context;
- std::optional<std::string> retryPolicy;
- std::optional<std::vector<nlohmann::json>> headers;
-
- if (!json_util::readJson(req, asyncResp->res, "Context", context,
- "DeliveryRetryPolicy", retryPolicy,
- "HttpHeaders", headers))
- {
- return;
- }
-
- if (context)
- {
- subValue->customText = *context;
- }
-
- if (headers)
- {
- subValue->httpHeaders = *headers;
- }
-
- if (retryPolicy)
- {
- if (std::find(supportedRetryPolicies.begin(),
- supportedRetryPolicies.end(),
- *retryPolicy) == supportedRetryPolicies.end())
- {
- messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
- "DeliveryRetryPolicy");
- return;
- }
- subValue->retryPolicy = *retryPolicy;
- subValue->updateRetryPolicy();
- }
-
- EventServiceManager::getInstance().updateSubscriptionData();
- }
-
- void doDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- if (!EventServiceManager::getInstance().isSubscriptionExist(params[0]))
- {
- asyncResp->res.result(boost::beast::http::status::not_found);
- return;
- }
- EventServiceManager::getInstance().deleteSubscription(params[0]);
- }
-};
+ EventServiceManager::getInstance().updateSubscriptionData();
+ });
+ BMCWEB_ROUTE(app, "redfish/v1/EventService/Subscriptions/<str>/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::delete_)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ if (!EventServiceManager::getInstance().isSubscriptionExist(
+ param))
+ {
+ asyncResp->res.result(
+ boost::beast::http::status::not_found);
+ return;
+ }
+ EventServiceManager::getInstance().deleteSubscription(param);
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/health.hpp b/redfish-core/lib/health.hpp
index cd4faa4..7dbab69 100644
--- a/redfish-core/lib/health.hpp
+++ b/redfish-core/lib/health.hpp
@@ -17,6 +17,7 @@
#include "async_resp.hpp"
+#include <app.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/container/flat_set.hpp>
#include <dbus_singleton.hpp>
diff --git a/redfish-core/lib/hypervisor_system.hpp b/redfish-core/lib/hypervisor_system.hpp
index 4a3a205..4c85b62 100644
--- a/redfish-core/lib/hypervisor_system.hpp
+++ b/redfish-core/lib/hypervisor_system.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <app.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
#include <dbus_singleton.hpp>
@@ -149,137 +150,6 @@
std::array<const char*, 1>{"xyz.openbmc_project.State.Host"});
}
-/**
- * Hypervisor Systems derived class for delivering Computer Systems Schema.
- */
-class HypervisorSystem : public Node
-{
- public:
- /*
- * Default Constructor
- */
- HypervisorSystem(App& app) : Node(app, "/redfish/v1/Systems/hypervisor/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}};
- }
-
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
- const std::variant<std::string>& /*hostName*/) {
- if (ec)
- {
- messages::resourceNotFound(asyncResp->res, "System",
- "hypervisor");
- return;
- }
- BMCWEB_LOG_DEBUG << "Hypervisor is available";
-
- asyncResp->res.jsonValue["@odata.type"] =
- "#ComputerSystem.v1_6_0.ComputerSystem";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/hypervisor";
- asyncResp->res.jsonValue["Description"] = "Hypervisor";
- asyncResp->res.jsonValue["Name"] = "Hypervisor";
- asyncResp->res.jsonValue["Id"] = "hypervisor";
- asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
- {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
- asyncResp->res.jsonValue["EthernetInterfaces"] = {
- {"@odata.id", "/redfish/v1/Systems/hypervisor/"
- "EthernetInterfaces"}};
- getHypervisorState(asyncResp);
- getHypervisorActions(asyncResp);
- // TODO: Add "SystemType" : "hypervisor"
- },
- "xyz.openbmc_project.Settings",
- "/xyz/openbmc_project/network/hypervisor",
- "org.freedesktop.DBus.Properties", "Get",
- "xyz.openbmc_project.Network.SystemConfiguration", "HostName");
- }
-};
-
-/**
- * HypervisorInterfaceCollection class to handle the GET and PATCH on Hypervisor
- * Interface
- */
-class HypervisorInterfaceCollection : public Node
-{
- public:
- HypervisorInterfaceCollection(App& app) :
- Node(app, "/redfish/v1/Systems/hypervisor/EthernetInterfaces/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}};
- }
-
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- const std::array<const char*, 1> interfaces = {
- "xyz.openbmc_project.Network.EthernetInterface"};
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code error,
- const std::vector<std::string>& ifaceList) {
- if (error)
- {
- messages::resourceNotFound(asyncResp->res, "System",
- "hypervisor");
- return;
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#EthernetInterfaceCollection."
- "EthernetInterfaceCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/hypervisor/EthernetInterfaces";
- asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet "
- "Interface Collection";
- asyncResp->res.jsonValue["Description"] =
- "Collection of Virtual Management "
- "Interfaces for the hypervisor";
-
- nlohmann::json& ifaceArray =
- asyncResp->res.jsonValue["Members"];
- ifaceArray = nlohmann::json::array();
- for (const std::string& iface : ifaceList)
- {
- sdbusplus::message::object_path path(iface);
- std::string name = path.filename();
- if (name.empty())
- {
- continue;
- }
-
- ifaceArray.push_back(
- {{"@odata.id", "/redfish/v1/Systems/hypervisor/"
- "EthernetInterfaces/" +
- name}});
- }
- asyncResp->res.jsonValue["Members@odata.count"] =
- ifaceArray.size();
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
- "/xyz/openbmc_project/network/hypervisor", 0, interfaces);
- }
-};
-
inline bool extractHypervisorInterfaceData(
const std::string& ethIfaceId, const GetManagedObjects& dbusData,
EthernetInterfaceData& ethData,
@@ -601,600 +471,636 @@
setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength);
}
-/**
- * HypervisorInterface derived class for delivering Ethernet Schema
- */
-class HypervisorInterface : public Node
+inline void parseInterfaceData(
+ nlohmann::json& jsonResponse, const std::string& ifaceId,
+ const EthernetInterfaceData& ethData,
+ const boost::container::flat_set<IPv4AddressData>& ipv4Data)
{
- public:
- /*
- * Default Constructor
- */
- HypervisorInterface(App& app) :
- Node(app, "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/",
- std::string())
+ jsonResponse["Id"] = ifaceId;
+ jsonResponse["@odata.id"] =
+ "/redfish/v1/Systems/hypervisor/EthernetInterfaces/" + ifaceId;
+ jsonResponse["InterfaceEnabled"] = true;
+ jsonResponse["MACAddress"] = ethData.mac_address;
+
+ jsonResponse["HostName"] = ethData.hostname;
+ jsonResponse["DHCPv4"]["DHCPEnabled"] =
+ translateDHCPEnabledToBool(ethData.DHCPEnabled, true);
+
+ nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
+ nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
+ ipv4Array = nlohmann::json::array();
+ ipv4StaticArray = nlohmann::json::array();
+ for (auto& ipv4Config : ipv4Data)
{
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}};
- }
-
- private:
- void parseInterfaceData(
- nlohmann::json& jsonResponse, const std::string& ifaceId,
- const EthernetInterfaceData& ethData,
- const boost::container::flat_set<IPv4AddressData>& ipv4Data)
- {
- jsonResponse["Id"] = ifaceId;
- jsonResponse["@odata.id"] =
- "/redfish/v1/Systems/hypervisor/EthernetInterfaces/" + ifaceId;
- jsonResponse["InterfaceEnabled"] = true;
- jsonResponse["MACAddress"] = ethData.mac_address;
-
- jsonResponse["HostName"] = ethData.hostname;
- jsonResponse["DHCPv4"]["DHCPEnabled"] =
- translateDHCPEnabledToBool(ethData.DHCPEnabled, true);
-
- nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
- nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
- ipv4Array = nlohmann::json::array();
- ipv4StaticArray = nlohmann::json::array();
- for (auto& ipv4Config : ipv4Data)
+ if (ipv4Config.isActive)
{
- if (ipv4Config.isActive)
- {
- ipv4Array.push_back({{"AddressOrigin", ipv4Config.origin},
- {"SubnetMask", ipv4Config.netmask},
- {"Address", ipv4Config.address},
- {"Gateway", ethData.default_gateway}});
- if (ipv4Config.origin == "Static")
- {
- ipv4StaticArray.push_back(
- {{"AddressOrigin", ipv4Config.origin},
- {"SubnetMask", ipv4Config.netmask},
- {"Address", ipv4Config.address},
- {"Gateway", ethData.default_gateway}});
- }
+ ipv4Array.push_back({{"AddressOrigin", ipv4Config.origin},
+ {"SubnetMask", ipv4Config.netmask},
+ {"Address", ipv4Config.address},
+ {"Gateway", ethData.default_gateway}});
+ if (ipv4Config.origin == "Static")
+ {
+ ipv4StaticArray.push_back(
+ {{"AddressOrigin", ipv4Config.origin},
+ {"SubnetMask", ipv4Config.netmask},
+ {"Address", ipv4Config.address},
+ {"Gateway", ethData.default_gateway}});
}
}
}
+}
- void handleHypervisorIPv4StaticPatch(
- const std::string& ifaceId, const nlohmann::json& input,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+inline void setDHCPEnabled(const std::string& ifaceId,
+ const bool& ipv4DHCPEnabled,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ const std::string dhcp = getDhcpEnabledEnumeration(ipv4DHCPEnabled, false);
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
+ "xyz.openbmc_project.Settings",
+ "/xyz/openbmc_project/network/hypervisor/" + ifaceId,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Network.EthernetInterface", "DHCPEnabled",
+ std::variant<std::string>{dhcp});
+
+ // Set the IPv4 address origin to the DHCP / Static as per the new value
+ // of the DHCPEnabled property
+ std::string origin;
+ if (ipv4DHCPEnabled == false)
{
- if ((!input.is_array()) || input.empty())
+ origin = "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
+ }
+ else
+ {
+ // DHCPEnabled is set to true. Delete the current IPv4 settings
+ // to receive the new values from DHCP server.
+ deleteHypervisorIPv4(ifaceId, asyncResp);
+ origin = "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
+ }
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "DBUS response error " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Hypervisor IPaddress Origin is Set";
+ },
+ "xyz.openbmc_project.Settings",
+ "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0",
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Network.IP", "Origin",
+ std::variant<std::string>(origin));
+}
+
+inline void handleHypervisorIPv4StaticPatch(
+ const std::string& ifaceId, const nlohmann::json& input,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ if ((!input.is_array()) || input.empty())
+ {
+ messages::propertyValueTypeError(asyncResp->res, input.dump(),
+ "IPv4StaticAddresses");
+ return;
+ }
+
+ // Hypervisor considers the first IP address in the array list
+ // as the Hypervisor's virtual management interface supports single IPv4
+ // address
+ const nlohmann::json& thisJson = input[0];
+
+ // For the error string
+ std::string pathString = "IPv4StaticAddresses/1";
+
+ if (!thisJson.is_null() && !thisJson.empty())
+ {
+ std::optional<std::string> address;
+ std::optional<std::string> subnetMask;
+ std::optional<std::string> gateway;
+ nlohmann::json thisJsonCopy = thisJson;
+ if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
+ address, "SubnetMask", subnetMask, "Gateway",
+ gateway))
{
- messages::propertyValueTypeError(asyncResp->res, input.dump(),
- "IPv4StaticAddresses");
+ messages::propertyValueFormatError(
+ asyncResp->res,
+ thisJson.dump(2, ' ', true,
+ nlohmann::json::error_handler_t::replace),
+ pathString);
return;
}
- // Hypervisor considers the first IP address in the array list
- // as the Hypervisor's virtual management interface supports single IPv4
- // address
- const nlohmann::json& thisJson = input[0];
-
- // For the error string
- std::string pathString = "IPv4StaticAddresses/1";
-
- if (!thisJson.is_null() && !thisJson.empty())
+ uint8_t prefixLength = 0;
+ bool errorInEntry = false;
+ if (address)
{
- std::optional<std::string> address;
- std::optional<std::string> subnetMask;
- std::optional<std::string> gateway;
- nlohmann::json thisJsonCopy = thisJson;
- if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
- address, "SubnetMask", subnetMask,
- "Gateway", gateway))
+ if (!ipv4VerifyIpAndGetBitcount(*address))
{
- messages::propertyValueFormatError(
- asyncResp->res,
- thisJson.dump(2, ' ', true,
- nlohmann::json::error_handler_t::replace),
- pathString);
- return;
- }
-
- uint8_t prefixLength = 0;
- bool errorInEntry = false;
- if (address)
- {
- if (!ipv4VerifyIpAndGetBitcount(*address))
- {
- messages::propertyValueFormatError(asyncResp->res, *address,
- pathString + "/Address");
- errorInEntry = true;
- }
- }
- else
- {
- messages::propertyMissing(asyncResp->res,
- pathString + "/Address");
+ messages::propertyValueFormatError(asyncResp->res, *address,
+ pathString + "/Address");
errorInEntry = true;
}
-
- if (subnetMask)
- {
- if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength))
- {
- messages::propertyValueFormatError(
- asyncResp->res, *subnetMask,
- pathString + "/SubnetMask");
- errorInEntry = true;
- }
- }
- else
- {
- messages::propertyMissing(asyncResp->res,
- pathString + "/SubnetMask");
- errorInEntry = true;
- }
-
- if (gateway)
- {
- if (!ipv4VerifyIpAndGetBitcount(*gateway))
- {
- messages::propertyValueFormatError(asyncResp->res, *gateway,
- pathString + "/Gateway");
- errorInEntry = true;
- }
- }
- else
- {
- messages::propertyMissing(asyncResp->res,
- pathString + "/Gateway");
- errorInEntry = true;
- }
-
- if (errorInEntry)
- {
- return;
- }
-
- BMCWEB_LOG_DEBUG << "Calling createHypervisorIPv4 on : " << ifaceId
- << "," << *address;
- createHypervisorIPv4(ifaceId, prefixLength, *gateway, *address,
- asyncResp);
- // Set the DHCPEnabled to false since the Static IPv4 is set
- setDHCPEnabled(ifaceId, false, asyncResp);
}
else
{
- if (thisJson.is_null())
+ messages::propertyMissing(asyncResp->res, pathString + "/Address");
+ errorInEntry = true;
+ }
+
+ if (subnetMask)
+ {
+ if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength))
{
- deleteHypervisorIPv4(ifaceId, asyncResp);
+ messages::propertyValueFormatError(asyncResp->res, *subnetMask,
+ pathString + "/SubnetMask");
+ errorInEntry = true;
}
}
- }
-
- bool isHostnameValid(const std::string& hostName)
- {
- // As per RFC 1123
- // Allow up to 255 characters
- if (hostName.length() > 255)
+ else
{
- return false;
+ messages::propertyMissing(asyncResp->res,
+ pathString + "/SubnetMask");
+ errorInEntry = true;
}
- // Validate the regex
- const std::regex pattern(
- "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
- return std::regex_match(hostName, pattern);
- }
-
- void
- handleHostnamePatch(const std::string& hostName,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
- {
- if (!isHostnameValid(hostName))
+ if (gateway)
{
- messages::propertyValueFormatError(asyncResp->res, hostName,
- "HostName");
+ if (!ipv4VerifyIpAndGetBitcount(*gateway))
+ {
+ messages::propertyValueFormatError(asyncResp->res, *gateway,
+ pathString + "/Gateway");
+ errorInEntry = true;
+ }
+ }
+ else
+ {
+ messages::propertyMissing(asyncResp->res, pathString + "/Gateway");
+ errorInEntry = true;
+ }
+
+ if (errorInEntry)
+ {
return;
}
- asyncResp->res.jsonValue["HostName"] = hostName;
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- }
- },
- "xyz.openbmc_project.Settings",
- "/xyz/openbmc_project/network/hypervisor",
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
- std::variant<std::string>(hostName));
+ BMCWEB_LOG_DEBUG << "Calling createHypervisorIPv4 on : " << ifaceId
+ << "," << *address;
+ createHypervisorIPv4(ifaceId, prefixLength, *gateway, *address,
+ asyncResp);
+ // Set the DHCPEnabled to false since the Static IPv4 is set
+ setDHCPEnabled(ifaceId, false, asyncResp);
}
-
- void setIPv4InterfaceEnabled(
- const std::string& ifaceId, const bool& isActive,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+ else
{
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
- },
- "xyz.openbmc_project.Settings",
- "/xyz/openbmc_project/network/hypervisor/" + ifaceId +
- "/ipv4/addr0",
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Object.Enable", "Enabled",
- std::variant<bool>(isActive));
- }
-
- void setDHCPEnabled(const std::string& ifaceId, const bool& ipv4DHCPEnabled,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
- {
- const std::string dhcp =
- getDhcpEnabledEnumeration(ipv4DHCPEnabled, false);
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
- },
- "xyz.openbmc_project.Settings",
- "/xyz/openbmc_project/network/hypervisor/" + ifaceId,
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Network.EthernetInterface", "DHCPEnabled",
- std::variant<std::string>{dhcp});
-
- // Set the IPv4 address origin to the DHCP / Static as per the new value
- // of the DHCPEnabled property
- std::string origin;
- if (ipv4DHCPEnabled == false)
+ if (thisJson.is_null())
{
- origin = "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
- }
- else
- {
- // DHCPEnabled is set to true. Delete the current IPv4 settings
- // to receive the new values from DHCP server.
deleteHypervisorIPv4(ifaceId, asyncResp);
- origin = "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
}
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "DBUS response error " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
- BMCWEB_LOG_DEBUG << "Hypervisor IPaddress Origin is Set";
- },
- "xyz.openbmc_project.Settings",
- "/xyz/openbmc_project/network/hypervisor/" + ifaceId +
- "/ipv4/addr0",
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Network.IP", "Origin",
- std::variant<std::string>(origin));
}
+}
+
+inline bool isHostnameValid(const std::string& hostName)
+{
+ // As per RFC 1123
+ // Allow up to 255 characters
+ if (hostName.length() > 255)
+ {
+ return false;
+ }
+ // Validate the regex
+ const std::regex pattern(
+ "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
+
+ return std::regex_match(hostName, pattern);
+}
+
+inline void
+ handleHostnamePatch(const std::string& hostName,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ if (!isHostnameValid(hostName))
+ {
+ messages::propertyValueFormatError(asyncResp->res, hostName,
+ "HostName");
+ return;
+ }
+
+ asyncResp->res.jsonValue["HostName"] = hostName;
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ }
+ },
+ "xyz.openbmc_project.Settings",
+ "/xyz/openbmc_project/network/hypervisor",
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
+ std::variant<std::string>(hostName));
+}
+
+inline void
+ setIPv4InterfaceEnabled(const std::string& ifaceId, const bool& isActive,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
+ "xyz.openbmc_project.Settings",
+ "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0",
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Object.Enable", "Enabled",
+ std::variant<bool>(isActive));
+}
+
+inline void requestRoutesHypervisorSystems(App& app)
+{
+ /**
+ * Hypervisor Systems derived class for delivering Computer Systems Schema.
+ */
+
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec,
+ const std::variant<std::string>& /*hostName*/) {
+ if (ec)
+ {
+ messages::resourceNotFound(asyncResp->res, "System",
+ "hypervisor");
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Hypervisor is available";
+
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#ComputerSystem.v1_6_0.ComputerSystem";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/hypervisor";
+ asyncResp->res.jsonValue["Description"] = "Hypervisor";
+ asyncResp->res.jsonValue["Name"] = "Hypervisor";
+ asyncResp->res.jsonValue["Id"] = "hypervisor";
+ asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
+ {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
+ asyncResp->res.jsonValue["EthernetInterfaces"] = {
+ {"@odata.id", "/redfish/v1/Systems/hypervisor/"
+ "EthernetInterfaces"}};
+ getHypervisorState(asyncResp);
+ getHypervisorActions(asyncResp);
+ // TODO: Add "SystemType" : "hypervisor"
+ },
+ "xyz.openbmc_project.Settings",
+ "/xyz/openbmc_project/network/hypervisor",
+ "org.freedesktop.DBus.Properties", "Get",
+ "xyz.openbmc_project.Network.SystemConfiguration",
+ "HostName");
+ });
/**
- * Functions triggers appropriate requests on DBus
+ * HypervisorInterfaceCollection class to handle the GET and PATCH on
+ * Hypervisor Interface
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- getHypervisorIfaceData(
- params[0],
- [this, asyncResp, ifaceId{std::string(params[0])}](
- const bool& success, const EthernetInterfaceData& ethData,
- const boost::container::flat_set<IPv4AddressData>& ipv4Data) {
- if (!success)
- {
- messages::resourceNotFound(asyncResp->res,
- "EthernetInterface", ifaceId);
- return;
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#EthernetInterface.v1_5_1.EthernetInterface";
- asyncResp->res.jsonValue["Name"] =
- "Hypervisor Ethernet Interface";
- asyncResp->res.jsonValue["Description"] =
- "Hypervisor's Virtual Management Ethernet Interface";
- parseInterfaceData(asyncResp->res.jsonValue, ifaceId, ethData,
- ipv4Data);
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/EthernetInterfaces/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ const std::array<const char*, 1> interfaces = {
+ "xyz.openbmc_project.Network.EthernetInterface"};
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code error,
+ const std::vector<std::string>& ifaceList) {
+ if (error)
+ {
+ messages::resourceNotFound(asyncResp->res, "System",
+ "hypervisor");
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#EthernetInterfaceCollection."
+ "EthernetInterfaceCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/hypervisor/EthernetInterfaces";
+ asyncResp->res.jsonValue["Name"] =
+ "Hypervisor Ethernet "
+ "Interface Collection";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of Virtual Management "
+ "Interfaces for the hypervisor";
+
+ nlohmann::json& ifaceArray =
+ asyncResp->res.jsonValue["Members"];
+ ifaceArray = nlohmann::json::array();
+ for (const std::string& iface : ifaceList)
+ {
+ sdbusplus::message::object_path path(iface);
+ std::string name = path.filename();
+ if (name.empty())
+ {
+ continue;
+ }
+
+ ifaceArray.push_back(
+ {{"@odata.id", "/redfish/v1/Systems/hypervisor/"
+ "EthernetInterfaces/" +
+ name}});
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ ifaceArray.size();
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
+ "/xyz/openbmc_project/network/hypervisor", 0, interfaces);
});
- }
- void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>& params) override
- {
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::get)([](const crow::Request&,
+ const std::shared_ptr<
+ bmcweb::AsyncResp>& asyncResp,
+ const std::string& id) {
+ getHypervisorIfaceData(
+ id,
+ [asyncResp, ifaceId{std::string(id)}](
+ const bool& success, const EthernetInterfaceData& ethData,
+ const boost::container::flat_set<IPv4AddressData>&
+ ipv4Data) {
+ if (!success)
+ {
+ messages::resourceNotFound(
+ asyncResp->res, "EthernetInterface", ifaceId);
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#EthernetInterface.v1_5_1.EthernetInterface";
+ asyncResp->res.jsonValue["Name"] =
+ "Hypervisor Ethernet Interface";
+ asyncResp->res.jsonValue["Description"] =
+ "Hypervisor's Virtual Management Ethernet Interface";
+ parseInterfaceData(asyncResp->res.jsonValue, ifaceId,
+ ethData, ipv4Data);
+ });
+ });
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/")
+ .privileges({"ConfigureComponents"})
+ .methods(
+ boost::beast::http::verb::
+ patch)([](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& ifaceId) {
+ std::optional<std::string> hostName;
+ std::optional<std::vector<nlohmann::json>> ipv4StaticAddresses;
+ std::optional<nlohmann::json> ipv4Addresses;
+ std::optional<nlohmann::json> dhcpv4;
+ std::optional<bool> ipv4DHCPEnabled;
- const std::string& ifaceId = params[0];
- std::optional<std::string> hostName;
- std::optional<std::vector<nlohmann::json>> ipv4StaticAddresses;
- std::optional<nlohmann::json> ipv4Addresses;
- std::optional<nlohmann::json> dhcpv4;
- std::optional<bool> ipv4DHCPEnabled;
-
- if (!json_util::readJson(req, asyncResp->res, "HostName", hostName,
- "IPv4StaticAddresses", ipv4StaticAddresses,
- "IPv4Addresses", ipv4Addresses, "DHCPv4",
- dhcpv4))
- {
- return;
- }
-
- if (ipv4Addresses)
- {
- messages::propertyNotWritable(asyncResp->res, "IPv4Addresses");
- }
-
- if (dhcpv4)
- {
- if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled",
- ipv4DHCPEnabled))
+ if (!json_util::readJson(req, asyncResp->res, "HostName", hostName,
+ "IPv4StaticAddresses", ipv4StaticAddresses,
+ "IPv4Addresses", ipv4Addresses, "DHCPv4",
+ dhcpv4))
{
return;
}
- }
- getHypervisorIfaceData(
- ifaceId,
- [this, asyncResp, ifaceId, hostName = std::move(hostName),
- ipv4StaticAddresses = std::move(ipv4StaticAddresses),
- ipv4DHCPEnabled, dhcpv4 = std::move(dhcpv4)](
- const bool& success, const EthernetInterfaceData& ethData,
- const boost::container::flat_set<IPv4AddressData>&) {
- if (!success)
+ if (ipv4Addresses)
+ {
+ messages::propertyNotWritable(asyncResp->res, "IPv4Addresses");
+ }
+
+ if (dhcpv4)
+ {
+ if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled",
+ ipv4DHCPEnabled))
{
- messages::resourceNotFound(asyncResp->res,
- "EthernetInterface", ifaceId);
return;
}
+ }
- if (ipv4StaticAddresses)
- {
- const nlohmann::json& ipv4Static = *ipv4StaticAddresses;
- if (ipv4Static.begin() == ipv4Static.end())
+ getHypervisorIfaceData(
+ ifaceId,
+ [asyncResp, ifaceId, hostName = std::move(hostName),
+ ipv4StaticAddresses = std::move(ipv4StaticAddresses),
+ ipv4DHCPEnabled, dhcpv4 = std::move(dhcpv4)](
+ const bool& success, const EthernetInterfaceData& ethData,
+ const boost::container::flat_set<IPv4AddressData>&) {
+ if (!success)
{
- messages::propertyValueTypeError(
- asyncResp->res,
- ipv4Static.dump(
- 2, ' ', true,
- nlohmann::json::error_handler_t::replace),
- "IPv4StaticAddresses");
+ messages::resourceNotFound(
+ asyncResp->res, "EthernetInterface", ifaceId);
return;
}
- // One and only one hypervisor instance supported
- if (ipv4Static.size() != 1)
+ if (ipv4StaticAddresses)
{
- messages::propertyValueFormatError(
- asyncResp->res,
- ipv4Static.dump(
- 2, ' ', true,
- nlohmann::json::error_handler_t::replace),
- "IPv4StaticAddresses");
- return;
+ const nlohmann::json& ipv4Static = *ipv4StaticAddresses;
+ if (ipv4Static.begin() == ipv4Static.end())
+ {
+ messages::propertyValueTypeError(
+ asyncResp->res,
+ ipv4Static.dump(
+ 2, ' ', true,
+ nlohmann::json::error_handler_t::replace),
+ "IPv4StaticAddresses");
+ return;
+ }
+
+ // One and only one hypervisor instance supported
+ if (ipv4Static.size() != 1)
+ {
+ messages::propertyValueFormatError(
+ asyncResp->res,
+ ipv4Static.dump(
+ 2, ' ', true,
+ nlohmann::json::error_handler_t::replace),
+ "IPv4StaticAddresses");
+ return;
+ }
+
+ const nlohmann::json& ipv4Json = ipv4Static[0];
+ // Check if the param is 'null'. If its null, it means
+ // that user wants to delete the IP address. Deleting
+ // the IP address is allowed only if its statically
+ // configured. Deleting the address originated from DHCP
+ // is not allowed.
+ if ((ipv4Json.is_null()) &&
+ (translateDHCPEnabledToBool(ethData.DHCPEnabled,
+ true)))
+ {
+ BMCWEB_LOG_INFO
+ << "Ignoring the delete on ipv4StaticAddresses "
+ "as the interface is DHCP enabled";
+ }
+ else
+ {
+ handleHypervisorIPv4StaticPatch(ifaceId, ipv4Static,
+ asyncResp);
+ }
}
- const nlohmann::json& ipv4Json = ipv4Static[0];
- // Check if the param is 'null'. If its null, it means that
- // user wants to delete the IP address. Deleting the IP
- // address is allowed only if its statically configured.
- // Deleting the address originated from DHCP is not allowed.
- if ((ipv4Json.is_null()) &&
- (translateDHCPEnabledToBool(ethData.DHCPEnabled, true)))
+ if (hostName)
{
- BMCWEB_LOG_INFO
- << "Ignoring the delete on ipv4StaticAddresses "
- "as the interface is DHCP enabled";
+ handleHostnamePatch(*hostName, asyncResp);
}
- else
+
+ if (dhcpv4)
{
- handleHypervisorIPv4StaticPatch(ifaceId, ipv4Static,
- asyncResp);
+ setDHCPEnabled(ifaceId, *ipv4DHCPEnabled, asyncResp);
}
- }
- if (hostName)
- {
- handleHostnamePatch(*hostName, asyncResp);
- }
+ // Set this interface to disabled/inactive. This will be set
+ // to enabled/active by the pldm once the hypervisor
+ // consumes the updated settings from the user.
+ setIPv4InterfaceEnabled(ifaceId, false, asyncResp);
+ });
+ asyncResp->res.result(boost::beast::http::status::accepted);
+ });
- if (dhcpv4)
- {
- setDHCPEnabled(ifaceId, *ipv4DHCPEnabled, asyncResp);
- }
-
- // Set this interface to disabled/inactive. This will be set to
- // enabled/active by the pldm once the hypervisor consumes the
- // updated settings from the user.
- setIPv4InterfaceEnabled(ifaceId, false, asyncResp);
- });
- asyncResp->res.result(boost::beast::http::status::accepted);
- }
-};
-
-/**
- * HypervisorResetActionInfo derived class for delivering Computer Systems
- * ResetType AllowableValues using ResetInfo schema.
- */
-class HypervisorResetActionInfo : public Node
-{
- public:
- /*
- * Default Constructor
- */
- HypervisorResetActionInfo(App& app) :
- Node(app, "/redfish/v1/Systems/hypervisor/ResetActionInfo/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- // Only return action info if hypervisor D-Bus object present
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/ResetActionInfo/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ // Only return action info if hypervisor D-Bus object present
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](
+ const boost::system::error_code ec,
const std::vector<std::pair<
std::string, std::vector<std::string>>>& objInfo) {
- if (ec)
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+
+ // No hypervisor objects found by mapper
+ if (ec.value() == boost::system::errc::io_error)
+ {
+ messages::resourceNotFound(asyncResp->res,
+ "hypervisor",
+ "ResetActionInfo");
+ return;
+ }
+
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ // One and only one hypervisor instance supported
+ if (objInfo.size() != 1)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ // The hypervisor object only support the ability to
+ // turn On The system object Action should be utilized
+ // for other operations
+ asyncResp->res.jsonValue = {
+ {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
+ {"@odata.id",
+ "/redfish/v1/Systems/hypervisor/ResetActionInfo"},
+ {"Name", "Reset Action Info"},
+ {"Id", "ResetActionInfo"},
+ {"Parameters",
+ {{{"Name", "ResetType"},
+ {"Required", true},
+ {"DataType", "String"},
+ {"AllowableValues", {"On"}}}}}};
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetObject",
+ "/xyz/openbmc_project/state/hypervisor0",
+ std::array<const char*, 1>{
+ "xyz.openbmc_project.State.Host"});
+ });
+
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ std::optional<std::string> resetType;
+ if (!json_util::readJson(req, asyncResp->res, "ResetType",
+ resetType))
{
- BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
-
- // No hypervisor objects found by mapper
- if (ec.value() == boost::system::errc::io_error)
- {
- messages::resourceNotFound(asyncResp->res, "hypervisor",
- "ResetActionInfo");
- return;
- }
-
- messages::internalError(asyncResp->res);
+ // readJson adds appropriate error to response
return;
}
- // One and only one hypervisor instance supported
- if (objInfo.size() != 1)
+ if (!resetType)
{
- messages::internalError(asyncResp->res);
+ messages::actionParameterMissing(
+ asyncResp->res, "ComputerSystem.Reset", "ResetType");
return;
}
- // The hypervisor object only support the ability to turn On
- // The system object Action should be utilized for other
- // operations
- asyncResp->res.jsonValue = {
- {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
- {"@odata.id",
- "/redfish/v1/Systems/hypervisor/ResetActionInfo"},
- {"Name", "Reset Action Info"},
- {"Id", "ResetActionInfo"},
- {"Parameters",
- {{{"Name", "ResetType"},
- {"Required", true},
- {"DataType", "String"},
- {"AllowableValues", {"On"}}}}}};
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetObject",
- "/xyz/openbmc_project/state/hypervisor0",
- std::array<const char*, 1>{"xyz.openbmc_project.State.Host"});
- }
-};
-
-/**
- * HypervisorActionsReset class supports the POST method for Reset action.
- * The class sends data directly to D-Bus.
- */
-class HypervisorActionsReset : public Node
-{
- public:
- HypervisorActionsReset(App& app) :
- Node(app,
- "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- /**
- * Function handles POST method request.
- * Analyzes POST body message before sends Reset request data to D-Bus.
- */
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
-
- std::optional<std::string> resetType;
- if (!json_util::readJson(req, asyncResp->res, "ResetType", resetType))
- {
- // readJson adds appropriate error to response
- return;
- }
-
- if (!resetType)
- {
- messages::actionParameterMissing(
- asyncResp->res, "ComputerSystem.Reset", "ResetType");
- return;
- }
-
- // Hypervisor object only support On operation
- if (resetType != "On")
- {
- messages::propertyValueNotInList(asyncResp->res, *resetType,
- "ResetType");
- return;
- }
-
- std::string command = "xyz.openbmc_project.State.Host.Transition.On";
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, resetType](const boost::system::error_code ec) {
- if (ec)
+ // Hypervisor object only support On operation
+ if (resetType != "On")
{
- BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
- if (ec.value() == boost::asio::error::invalid_argument)
- {
- messages::actionParameterNotSupported(
- asyncResp->res, *resetType, "Reset");
- return;
- }
-
- if (ec.value() == boost::asio::error::host_unreachable)
- {
- messages::resourceNotFound(asyncResp->res, "Actions",
- "Reset");
- return;
- }
-
- messages::internalError(asyncResp->res);
+ messages::propertyValueNotInList(asyncResp->res, *resetType,
+ "ResetType");
return;
}
- messages::success(asyncResp->res);
- },
- "xyz.openbmc_project.State.Hypervisor",
- "/xyz/openbmc_project/state/hypervisor0",
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.State.Host", "RequestedHostTransition",
- std::variant<std::string>{std::move(command)});
- }
-};
+
+ std::string command =
+ "xyz.openbmc_project.State.Host.Transition.On";
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, resetType](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
+ if (ec.value() ==
+ boost::asio::error::invalid_argument)
+ {
+ messages::actionParameterNotSupported(
+ asyncResp->res, *resetType, "Reset");
+ return;
+ }
+
+ if (ec.value() ==
+ boost::asio::error::host_unreachable)
+ {
+ messages::resourceNotFound(asyncResp->res,
+ "Actions", "Reset");
+ return;
+ }
+
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ messages::success(asyncResp->res);
+ },
+ "xyz.openbmc_project.State.Hypervisor",
+ "/xyz/openbmc_project/state/hypervisor0",
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.State.Host", "RequestedHostTransition",
+ std::variant<std::string>{std::move(command)});
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/led.hpp b/redfish-core/lib/led.hpp
index fe1842f..1fdf5e7 100644
--- a/redfish-core/lib/led.hpp
+++ b/redfish-core/lib/led.hpp
@@ -19,6 +19,8 @@
#include "dbus_utility.hpp"
#include "redfish_util.hpp"
+#include <app.hpp>
+
#include <variant>
namespace redfish
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index efed764..b04d0f9 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -15,7 +15,6 @@
*/
#pragma once
-#include "node.hpp"
#include "registries.hpp"
#include "registries/base_message_registry.hpp"
#include "registries/openbmc_message_registry.hpp"
@@ -24,6 +23,7 @@
#include <systemd/sd-journal.h>
#include <unistd.h>
+#include <app.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/beast/core/span.hpp>
@@ -129,9 +129,9 @@
return "";
}
-static int getJournalMetadata(sd_journal* journal,
- const std::string_view& field,
- std::string_view& contents)
+inline static int getJournalMetadata(sd_journal* journal,
+ const std::string_view& field,
+ std::string_view& contents)
{
const char* data = nullptr;
size_t length = 0;
@@ -149,9 +149,9 @@
return ret;
}
-static int getJournalMetadata(sd_journal* journal,
- const std::string_view& field, const int& base,
- long int& contents)
+inline static int getJournalMetadata(sd_journal* journal,
+ const std::string_view& field,
+ const int& base, long int& contents)
{
int ret = 0;
std::string_view metadata;
@@ -165,7 +165,8 @@
return ret;
}
-static bool getEntryTimestamp(sd_journal* journal, std::string& entryTimestamp)
+inline static bool getEntryTimestamp(sd_journal* journal,
+ std::string& entryTimestamp)
{
int ret = 0;
uint64_t timestamp = 0;
@@ -231,8 +232,8 @@
return true;
}
-static bool getUniqueEntryID(sd_journal* journal, std::string& entryID,
- const bool firstEntry = true)
+inline static bool getUniqueEntryID(sd_journal* journal, std::string& entryID,
+ const bool firstEntry = true)
{
int ret = 0;
static uint64_t prevTs = 0;
@@ -311,7 +312,7 @@
return true;
}
-static bool
+inline static bool
getTimestampFromID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& entryID, uint64_t& timestamp,
uint64_t& index)
@@ -864,7 +865,7 @@
dumpType});
}
-static void parseCrashdumpParameters(
+inline static void parseCrashdumpParameters(
const std::vector<std::pair<std::string, VariantType>>& params,
std::string& filename, std::string& timestamp, std::string& logfile)
{
@@ -901,171 +902,144 @@
}
constexpr char const* postCodeIface = "xyz.openbmc_project.State.Boot.PostCode";
-class SystemLogServiceCollection : public Node
+inline void requestRoutesSystemLogServiceCollection(App& app)
{
- public:
- SystemLogServiceCollection(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
/**
* Functions triggers appropriate requests on DBus
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- // Collections don't include the static data added by SubRoute because
- // it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogServiceCollection.LogServiceCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices";
- asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
- asyncResp->res.jsonValue["Description"] =
- "Collection of LogServices for this Computer System";
- nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
- logServiceArray = nlohmann::json::array();
- logServiceArray.push_back(
- {{"@odata.id", "/redfish/v1/Systems/system/LogServices/EventLog"}});
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+
+ {
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogServiceCollection.LogServiceCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices";
+ asyncResp->res.jsonValue["Name"] =
+ "System Log Services Collection";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of LogServices for this Computer System";
+ nlohmann::json& logServiceArray =
+ asyncResp->res.jsonValue["Members"];
+ logServiceArray = nlohmann::json::array();
+ logServiceArray.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Systems/system/LogServices/EventLog"}});
#ifdef BMCWEB_ENABLE_REDFISH_DUMP_LOG
- logServiceArray.push_back(
- {{"@odata.id", "/redfish/v1/Systems/system/LogServices/Dump"}});
+ logServiceArray.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Systems/system/LogServices/Dump"}});
#endif
#ifdef BMCWEB_ENABLE_REDFISH_CPU_LOG
- logServiceArray.push_back(
- {{"@odata.id",
- "/redfish/v1/Systems/system/LogServices/Crashdump"}});
+ logServiceArray.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Systems/system/LogServices/Crashdump"}});
#endif
- asyncResp->res.jsonValue["Members@odata.count"] =
- logServiceArray.size();
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ logServiceArray.size();
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
- const std::vector<std::string>& subtreePath) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << ec;
- return;
- }
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec,
+ const std::vector<std::string>& subtreePath) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << ec;
+ return;
+ }
- for (auto& pathStr : subtreePath)
+ for (auto& pathStr : subtreePath)
+ {
+ if (pathStr.find("PostCode") != std::string::npos)
+ {
+ nlohmann::json& logServiceArrayLocal =
+ asyncResp->res.jsonValue["Members"];
+ logServiceArrayLocal.push_back(
+ {{"@odata.id", "/redfish/v1/Systems/system/"
+ "LogServices/PostCodes"}});
+ asyncResp->res
+ .jsonValue["Members@odata.count"] =
+ logServiceArrayLocal.size();
+ return;
+ }
+ }
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
+ 0, std::array<const char*, 1>{postCodeIface});
+ });
+}
+
+inline void requestRoutesEventLogService(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/EventLog/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::
+ get)([](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/EventLog";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogService.v1_1_0.LogService";
+ asyncResp->res.jsonValue["Name"] = "Event Log Service";
+ asyncResp->res.jsonValue["Description"] =
+ "System Event Log Service";
+ asyncResp->res.jsonValue["Id"] = "EventLog";
+ asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+ asyncResp->res.jsonValue["Entries"] = {
+ {"@odata.id",
+ "/redfish/v1/Systems/system/LogServices/EventLog/Entries"}};
+ asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = {
+
+ {"target", "/redfish/v1/Systems/system/LogServices/EventLog/"
+ "Actions/LogService.ClearLog"}};
+ });
+}
+
+inline void requestRoutesJournalEventLogClear(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/EventLog/Actions/"
+ "LogService.ClearLog/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ // Clear the EventLog by deleting the log files
+ std::vector<std::filesystem::path> redfishLogFiles;
+ if (getRedfishLogFiles(redfishLogFiles))
{
- if (pathStr.find("PostCode") != std::string::npos)
+ for (const std::filesystem::path& file : redfishLogFiles)
{
- nlohmann::json& logServiceArrayLocal =
- asyncResp->res.jsonValue["Members"];
- logServiceArrayLocal.push_back(
- {{"@odata.id", "/redfish/v1/Systems/system/"
- "LogServices/PostCodes"}});
- asyncResp->res.jsonValue["Members@odata.count"] =
- logServiceArrayLocal.size();
- return;
+ std::error_code ec;
+ std::filesystem::remove(file, ec);
}
}
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/", 0,
- std::array<const char*, 1>{postCodeIface});
- }
-};
-class EventLogService : public Node
-{
- public:
- EventLogService(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/EventLog/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ // Reload rsyslog so it knows to start new log files
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "Failed to reload rsyslog: "
+ << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/EventLog";
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogService.v1_1_0.LogService";
- asyncResp->res.jsonValue["Name"] = "Event Log Service";
- asyncResp->res.jsonValue["Description"] = "System Event Log Service";
- asyncResp->res.jsonValue["Id"] = "EventLog";
- asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
- asyncResp->res.jsonValue["Entries"] = {
- {"@odata.id",
- "/redfish/v1/Systems/system/LogServices/EventLog/Entries"}};
- asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = {
-
- {"target", "/redfish/v1/Systems/system/LogServices/EventLog/"
- "Actions/LogService.ClearLog"}};
- }
-};
-
-class JournalEventLogClear : public Node
-{
- public:
- JournalEventLogClear(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/EventLog/Actions/"
- "LogService.ClearLog/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- // Clear the EventLog by deleting the log files
- std::vector<std::filesystem::path> redfishLogFiles;
- if (getRedfishLogFiles(redfishLogFiles))
- {
- for (const std::filesystem::path& file : redfishLogFiles)
- {
- std::error_code ec;
- std::filesystem::remove(file, ec);
- }
- }
-
- // Reload rsyslog so it knows to start new log files
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "Failed to reload rsyslog: " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
-
- messages::success(asyncResp->res);
- },
- "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
- "replace");
- }
-};
+ messages::success(asyncResp->res);
+ },
+ "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager", "ReloadUnit",
+ "rsyslog.service", "replace");
+ });
+}
static int fillEventLogEntryJson(const std::string& logEntryID,
const std::string& logEntry,
@@ -1164,800 +1138,718 @@
return 0;
}
-class JournalEventLogEntryCollection : public Node
+inline void requestRoutesJournalEventLogEntryCollection(App& app)
{
- public:
- JournalEventLogEntryCollection(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- uint64_t skip = 0;
- uint64_t top = maxEntriesPerPage; // Show max entries by default
- if (!getSkipParam(asyncResp, req, skip))
- {
- return;
- }
- if (!getTopParam(asyncResp, req, top))
- {
- return;
- }
- // Collections don't include the static data added by SubRoute because
- // it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/EventLog/Entries";
- asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of System Event Log Entries";
-
- nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
- logEntryArray = nlohmann::json::array();
- // Go through the log files and create a unique ID for each entry
- std::vector<std::filesystem::path> redfishLogFiles;
- getRedfishLogFiles(redfishLogFiles);
- uint64_t entryCount = 0;
- std::string logEntry;
-
- // Oldest logs are in the last file, so start there and loop backwards
- for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend();
- it++)
- {
- std::ifstream logStream(*it);
- if (!logStream.is_open())
- {
- continue;
- }
-
- // Reset the unique ID on the first entry
- bool firstEntry = true;
- while (std::getline(logStream, logEntry))
- {
- entryCount++;
- // Handle paging using skip (number of entries to skip from the
- // start) and top (number of entries to display)
- if (entryCount <= skip || entryCount > skip + top)
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/system/LogServices/EventLog/Entries/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ uint64_t skip = 0;
+ uint64_t top = maxEntriesPerPage; // Show max entries by default
+ if (!getSkipParam(asyncResp, req, skip))
{
- continue;
- }
-
- std::string idStr;
- if (!getUniqueEntryID(logEntry, idStr, firstEntry))
- {
- continue;
- }
-
- if (firstEntry)
- {
- firstEntry = false;
- }
-
- logEntryArray.push_back({});
- nlohmann::json& bmcLogEntry = logEntryArray.back();
- if (fillEventLogEntryJson(idStr, logEntry, bmcLogEntry) != 0)
- {
- messages::internalError(asyncResp->res);
return;
}
- }
- }
- asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
- if (skip + top < entryCount)
- {
- asyncResp->res.jsonValue["Members@odata.nextLink"] =
- "/redfish/v1/Systems/system/LogServices/EventLog/"
- "Entries?$skip=" +
- std::to_string(skip + top);
- }
- }
-};
-
-class JournalEventLogEntry : public Node
-{
- public:
- JournalEventLogEntry(App& app) :
- Node(app,
- "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& targetID = params[0];
-
- // Go through the log files and check the unique ID for each entry to
- // find the target entry
- std::vector<std::filesystem::path> redfishLogFiles;
- getRedfishLogFiles(redfishLogFiles);
- std::string logEntry;
-
- // Oldest logs are in the last file, so start there and loop backwards
- for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend();
- it++)
- {
- std::ifstream logStream(*it);
- if (!logStream.is_open())
- {
- continue;
- }
-
- // Reset the unique ID on the first entry
- bool firstEntry = true;
- while (std::getline(logStream, logEntry))
- {
- std::string idStr;
- if (!getUniqueEntryID(logEntry, idStr, firstEntry))
+ if (!getTopParam(asyncResp, req, top))
{
- continue;
- }
-
- if (firstEntry)
- {
- firstEntry = false;
- }
-
- if (idStr == targetID)
- {
- if (fillEventLogEntryJson(idStr, logEntry,
- asyncResp->res.jsonValue) != 0)
- {
- messages::internalError(asyncResp->res);
- return;
- }
return;
}
- }
- }
- // Requested ID was not found
- messages::resourceMissingAtURI(asyncResp->res, targetID);
- }
-};
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/EventLog/Entries";
+ asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of System Event Log Entries";
-class DBusEventLogEntryCollection : public Node
-{
- public:
- DBusEventLogEntryCollection(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- // Collections don't include the static data added by SubRoute because
- // it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/EventLog/Entries";
- asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of System Event Log Entries";
-
- // DBus implementation of EventLog/Entries
- // Make call to Logging Service to find all log entry objects
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
- GetManagedObjectsType& resp) {
- if (ec)
- {
- // TODO Handle for specific error code
- BMCWEB_LOG_ERROR
- << "getLogEntriesIfaceData resp_handler got error "
- << ec;
- messages::internalError(asyncResp->res);
- return;
- }
- nlohmann::json& entriesArray =
+ nlohmann::json& logEntryArray =
asyncResp->res.jsonValue["Members"];
- entriesArray = nlohmann::json::array();
- for (auto& objectPath : resp)
+ logEntryArray = nlohmann::json::array();
+ // Go through the log files and create a unique ID for each
+ // entry
+ std::vector<std::filesystem::path> redfishLogFiles;
+ getRedfishLogFiles(redfishLogFiles);
+ uint64_t entryCount = 0;
+ std::string logEntry;
+
+ // Oldest logs are in the last file, so start there and loop
+ // backwards
+ for (auto it = redfishLogFiles.rbegin();
+ it < redfishLogFiles.rend(); it++)
{
- uint32_t* id = nullptr;
- std::time_t timestamp{};
- std::time_t updateTimestamp{};
- std::string* severity = nullptr;
- std::string* message = nullptr;
- std::string* filePath = nullptr;
- bool resolved = false;
- for (auto& interfaceMap : objectPath.second)
- {
- if (interfaceMap.first ==
- "xyz.openbmc_project.Logging.Entry")
- {
- for (auto& propertyMap : interfaceMap.second)
- {
- if (propertyMap.first == "Id")
- {
- id = std::get_if<uint32_t>(
- &propertyMap.second);
- }
- else if (propertyMap.first == "Timestamp")
- {
- const uint64_t* millisTimeStamp =
- std::get_if<uint64_t>(
- &propertyMap.second);
- if (millisTimeStamp != nullptr)
- {
- timestamp = crow::utility::getTimestamp(
- *millisTimeStamp);
- }
- }
- else if (propertyMap.first == "UpdateTimestamp")
- {
- const uint64_t* millisTimeStamp =
- std::get_if<uint64_t>(
- &propertyMap.second);
- if (millisTimeStamp != nullptr)
- {
- updateTimestamp =
- crow::utility::getTimestamp(
- *millisTimeStamp);
- }
- }
- else if (propertyMap.first == "Severity")
- {
- severity = std::get_if<std::string>(
- &propertyMap.second);
- }
- else if (propertyMap.first == "Message")
- {
- message = std::get_if<std::string>(
- &propertyMap.second);
- }
- else if (propertyMap.first == "Resolved")
- {
- bool* resolveptr =
- std::get_if<bool>(&propertyMap.second);
- if (resolveptr == nullptr)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- resolved = *resolveptr;
- }
- }
- if (id == nullptr || message == nullptr ||
- severity == nullptr)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- }
- else if (interfaceMap.first ==
- "xyz.openbmc_project.Common.FilePath")
- {
- for (auto& propertyMap : interfaceMap.second)
- {
- if (propertyMap.first == "Path")
- {
- filePath = std::get_if<std::string>(
- &propertyMap.second);
- }
- }
- }
- }
- // Object path without the xyz.openbmc_project.Logging.Entry
- // interface, ignore and continue.
- if (id == nullptr || message == nullptr ||
- severity == nullptr)
+ std::ifstream logStream(*it);
+ if (!logStream.is_open())
{
continue;
}
- entriesArray.push_back({});
- nlohmann::json& thisEntry = entriesArray.back();
- thisEntry["@odata.type"] = "#LogEntry.v1_8_0.LogEntry";
- thisEntry["@odata.id"] = "/redfish/v1/Systems/system/"
- "LogServices/EventLog/Entries/" +
- std::to_string(*id);
- thisEntry["Name"] = "System Event Log Entry";
- thisEntry["Id"] = std::to_string(*id);
- thisEntry["Message"] = *message;
- thisEntry["Resolved"] = resolved;
- thisEntry["EntryType"] = "Event";
- thisEntry["Severity"] =
- translateSeverityDbusToRedfish(*severity);
- thisEntry["Created"] =
- crow::utility::getDateTime(timestamp);
- thisEntry["Modified"] =
- crow::utility::getDateTime(updateTimestamp);
- if (filePath != nullptr)
+
+ // Reset the unique ID on the first entry
+ bool firstEntry = true;
+ while (std::getline(logStream, logEntry))
{
- thisEntry["AdditionalDataURI"] =
- "/redfish/v1/Systems/system/LogServices/EventLog/"
- "Entries/" +
- std::to_string(*id) + "/attachment";
- }
- }
- std::sort(entriesArray.begin(), entriesArray.end(),
- [](const nlohmann::json& left,
- const nlohmann::json& right) {
- return (left["Id"] <= right["Id"]);
- });
- asyncResp->res.jsonValue["Members@odata.count"] =
- entriesArray.size();
- },
- "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging",
- "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
- }
-};
-
-class DBusEventLogEntry : public Node
-{
- public:
- DBusEventLogEntry(App& app) :
- Node(app,
- "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- std::string entryID = params[0];
- dbus::utility::escapePathForDbus(entryID);
-
- // DBus implementation of EventLog/Entries
- // Make call to Logging Service to find all log entry objects
- crow::connections::systemBus->async_method_call(
- [asyncResp, entryID](const boost::system::error_code ec,
- GetManagedPropertyType& resp) {
- if (ec.value() == EBADR)
- {
- messages::resourceNotFound(asyncResp->res, "EventLogEntry",
- entryID);
- return;
- }
- if (ec)
- {
- BMCWEB_LOG_ERROR
- << "EventLogEntry (DBus) resp_handler got error " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
- uint32_t* id = nullptr;
- std::time_t timestamp{};
- std::time_t updateTimestamp{};
- std::string* severity = nullptr;
- std::string* message = nullptr;
- std::string* filePath = nullptr;
- bool resolved = false;
-
- for (auto& propertyMap : resp)
- {
- if (propertyMap.first == "Id")
- {
- id = std::get_if<uint32_t>(&propertyMap.second);
- }
- else if (propertyMap.first == "Timestamp")
- {
- const uint64_t* millisTimeStamp =
- std::get_if<uint64_t>(&propertyMap.second);
- if (millisTimeStamp != nullptr)
+ entryCount++;
+ // Handle paging using skip (number of entries to skip
+ // from the start) and top (number of entries to
+ // display)
+ if (entryCount <= skip || entryCount > skip + top)
{
- timestamp =
- crow::utility::getTimestamp(*millisTimeStamp);
+ continue;
}
- }
- else if (propertyMap.first == "UpdateTimestamp")
- {
- const uint64_t* millisTimeStamp =
- std::get_if<uint64_t>(&propertyMap.second);
- if (millisTimeStamp != nullptr)
+
+ std::string idStr;
+ if (!getUniqueEntryID(logEntry, idStr, firstEntry))
{
- updateTimestamp =
- crow::utility::getTimestamp(*millisTimeStamp);
+ continue;
}
- }
- else if (propertyMap.first == "Severity")
- {
- severity =
- std::get_if<std::string>(&propertyMap.second);
- }
- else if (propertyMap.first == "Message")
- {
- message = std::get_if<std::string>(&propertyMap.second);
- }
- else if (propertyMap.first == "Resolved")
- {
- bool* resolveptr =
- std::get_if<bool>(&propertyMap.second);
- if (resolveptr == nullptr)
+
+ if (firstEntry)
+ {
+ firstEntry = false;
+ }
+
+ logEntryArray.push_back({});
+ nlohmann::json& bmcLogEntry = logEntryArray.back();
+ if (fillEventLogEntryJson(idStr, logEntry,
+ bmcLogEntry) != 0)
{
messages::internalError(asyncResp->res);
return;
}
- resolved = *resolveptr;
- }
- else if (propertyMap.first == "Path")
- {
- filePath =
- std::get_if<std::string>(&propertyMap.second);
}
}
- if (id == nullptr || message == nullptr || severity == nullptr)
+ asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
+ if (skip + top < entryCount)
{
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntry.v1_8_0.LogEntry";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/EventLog/Entries/" +
- std::to_string(*id);
- asyncResp->res.jsonValue["Name"] = "System Event Log Entry";
- asyncResp->res.jsonValue["Id"] = std::to_string(*id);
- asyncResp->res.jsonValue["Message"] = *message;
- asyncResp->res.jsonValue["Resolved"] = resolved;
- asyncResp->res.jsonValue["EntryType"] = "Event";
- asyncResp->res.jsonValue["Severity"] =
- translateSeverityDbusToRedfish(*severity);
- asyncResp->res.jsonValue["Created"] =
- crow::utility::getDateTime(timestamp);
- asyncResp->res.jsonValue["Modified"] =
- crow::utility::getDateTime(updateTimestamp);
- if (filePath != nullptr)
- {
- asyncResp->res.jsonValue["AdditionalDataURI"] =
+ asyncResp->res.jsonValue["Members@odata.nextLink"] =
"/redfish/v1/Systems/system/LogServices/EventLog/"
- "Entries/" +
- std::to_string(*id) + "/attachment";
+ "Entries?$skip=" +
+ std::to_string(skip + top);
}
- },
- "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging/entry/" + entryID,
- "org.freedesktop.DBus.Properties", "GetAll", "");
- }
+ });
+}
- void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>& params) override
- {
+inline void requestRoutesJournalEventLogEntry(App& app)
+{
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ const std::string& targetID = param;
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- std::string entryId = params[0];
+ // Go through the log files and check the unique ID for each
+ // entry to find the target entry
+ std::vector<std::filesystem::path> redfishLogFiles;
+ getRedfishLogFiles(redfishLogFiles);
+ std::string logEntry;
- std::optional<bool> resolved;
+ // Oldest logs are in the last file, so start there and loop
+ // backwards
+ for (auto it = redfishLogFiles.rbegin();
+ it < redfishLogFiles.rend(); it++)
+ {
+ std::ifstream logStream(*it);
+ if (!logStream.is_open())
+ {
+ continue;
+ }
- if (!json_util::readJson(req, asyncResp->res, "Resolved", resolved))
- {
- return;
- }
+ // Reset the unique ID on the first entry
+ bool firstEntry = true;
+ while (std::getline(logStream, logEntry))
+ {
+ std::string idStr;
+ if (!getUniqueEntryID(logEntry, idStr, firstEntry))
+ {
+ continue;
+ }
- if (resolved)
- {
- BMCWEB_LOG_DEBUG << "Set Resolved";
+ if (firstEntry)
+ {
+ firstEntry = false;
+ }
+ if (idStr == targetID)
+ {
+ if (fillEventLogEntryJson(
+ idStr, logEntry,
+ asyncResp->res.jsonValue) != 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ return;
+ }
+ }
+ }
+ // Requested ID was not found
+ messages::resourceMissingAtURI(asyncResp->res, targetID);
+ });
+}
+
+inline void requestRoutesDBusEventLogEntryCollection(App& app)
+{
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/system/LogServices/EventLog/Entries/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::
+ get)([](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/EventLog/Entries";
+ asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of System Event Log Entries";
+
+ // DBus implementation of EventLog/Entries
+ // Make call to Logging Service to find all log entry objects
crow::connections::systemBus->async_method_call(
- [asyncResp, resolved,
- entryId](const boost::system::error_code ec) {
+ [asyncResp](const boost::system::error_code ec,
+ GetManagedObjectsType& resp) {
if (ec)
{
- BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+ // TODO Handle for specific error code
+ BMCWEB_LOG_ERROR
+ << "getLogEntriesIfaceData resp_handler got error "
+ << ec;
messages::internalError(asyncResp->res);
return;
}
+ nlohmann::json& entriesArray =
+ asyncResp->res.jsonValue["Members"];
+ entriesArray = nlohmann::json::array();
+ for (auto& objectPath : resp)
+ {
+ uint32_t* id = nullptr;
+ std::time_t timestamp{};
+ std::time_t updateTimestamp{};
+ std::string* severity = nullptr;
+ std::string* message = nullptr;
+ std::string* filePath = nullptr;
+ bool resolved = false;
+ for (auto& interfaceMap : objectPath.second)
+ {
+ if (interfaceMap.first ==
+ "xyz.openbmc_project.Logging.Entry")
+ {
+ for (auto& propertyMap : interfaceMap.second)
+ {
+ if (propertyMap.first == "Id")
+ {
+ id = std::get_if<uint32_t>(
+ &propertyMap.second);
+ }
+ else if (propertyMap.first == "Timestamp")
+ {
+ const uint64_t* millisTimeStamp =
+ std::get_if<uint64_t>(
+ &propertyMap.second);
+ if (millisTimeStamp != nullptr)
+ {
+ timestamp =
+ crow::utility::getTimestamp(
+ *millisTimeStamp);
+ }
+ }
+ else if (propertyMap.first ==
+ "UpdateTimestamp")
+ {
+ const uint64_t* millisTimeStamp =
+ std::get_if<uint64_t>(
+ &propertyMap.second);
+ if (millisTimeStamp != nullptr)
+ {
+ updateTimestamp =
+ crow::utility::getTimestamp(
+ *millisTimeStamp);
+ }
+ }
+ else if (propertyMap.first == "Severity")
+ {
+ severity = std::get_if<std::string>(
+ &propertyMap.second);
+ }
+ else if (propertyMap.first == "Message")
+ {
+ message = std::get_if<std::string>(
+ &propertyMap.second);
+ }
+ else if (propertyMap.first == "Resolved")
+ {
+ bool* resolveptr = std::get_if<bool>(
+ &propertyMap.second);
+ if (resolveptr == nullptr)
+ {
+ messages::internalError(
+ asyncResp->res);
+ return;
+ }
+ resolved = *resolveptr;
+ }
+ }
+ if (id == nullptr || message == nullptr ||
+ severity == nullptr)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ }
+ else if (interfaceMap.first ==
+ "xyz.openbmc_project.Common.FilePath")
+ {
+ for (auto& propertyMap : interfaceMap.second)
+ {
+ if (propertyMap.first == "Path")
+ {
+ filePath = std::get_if<std::string>(
+ &propertyMap.second);
+ }
+ }
+ }
+ }
+ // Object path without the
+ // xyz.openbmc_project.Logging.Entry interface, ignore
+ // and continue.
+ if (id == nullptr || message == nullptr ||
+ severity == nullptr)
+ {
+ continue;
+ }
+ entriesArray.push_back({});
+ nlohmann::json& thisEntry = entriesArray.back();
+ thisEntry["@odata.type"] = "#LogEntry.v1_8_0.LogEntry";
+ thisEntry["@odata.id"] =
+ "/redfish/v1/Systems/system/"
+ "LogServices/EventLog/Entries/" +
+ std::to_string(*id);
+ thisEntry["Name"] = "System Event Log Entry";
+ thisEntry["Id"] = std::to_string(*id);
+ thisEntry["Message"] = *message;
+ thisEntry["Resolved"] = resolved;
+ thisEntry["EntryType"] = "Event";
+ thisEntry["Severity"] =
+ translateSeverityDbusToRedfish(*severity);
+ thisEntry["Created"] =
+ crow::utility::getDateTime(timestamp);
+ thisEntry["Modified"] =
+ crow::utility::getDateTime(updateTimestamp);
+ if (filePath != nullptr)
+ {
+ thisEntry["AdditionalDataURI"] =
+ "/redfish/v1/Systems/system/LogServices/"
+ "EventLog/"
+ "Entries/" +
+ std::to_string(*id) + "/attachment";
+ }
+ }
+ std::sort(entriesArray.begin(), entriesArray.end(),
+ [](const nlohmann::json& left,
+ const nlohmann::json& right) {
+ return (left["Id"] <= right["Id"]);
+ });
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ entriesArray.size();
},
- "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging/entry/" + entryId,
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Logging.Entry", "Resolved",
- std::variant<bool>(*resolved));
- }
- }
+ "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging",
+ "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+ });
+}
- void doDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- BMCWEB_LOG_DEBUG << "Do delete single event entries.";
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- std::string entryID = params[0];
-
- dbus::utility::escapePathForDbus(entryID);
-
- // Process response from Logging service.
- auto respHandler = [asyncResp,
- entryID](const boost::system::error_code ec) {
- BMCWEB_LOG_DEBUG << "EventLogEntry (DBus) doDelete callback: Done";
- if (ec)
- {
- if (ec.value() == EBADR)
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry",
- entryID);
- return;
- }
- // TODO Handle for specific error code
- BMCWEB_LOG_ERROR
- << "EventLogEntry (DBus) doDelete respHandler got error "
- << ec;
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
-
- asyncResp->res.result(boost::beast::http::status::ok);
- };
-
- // Make call to Logging service to request Delete Log
- crow::connections::systemBus->async_method_call(
- respHandler, "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging/entry/" + entryID,
- "xyz.openbmc_project.Object.Delete", "Delete");
- }
-};
-
-class DBusEventLogEntryDownload : public Node
+inline void requestRoutesDBusEventLogEntry(App& app)
{
- public:
- DBusEventLogEntryDownload(App& app) :
- Node(app,
- "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/"
- "attachment",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param)
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- std::string_view acceptHeader = req.getHeaderValue("Accept");
- // The iterators in boost/http/rfc7230.hpp end the string if '/' is
- // found, so replace it with arbitrary character '|' which is not part
- // of the Accept header syntax.
- std::string acceptStr =
- boost::replace_all_copy(std::string(acceptHeader), "/", "|");
- boost::beast::http::ext_list acceptTypes{acceptStr};
- bool supported = false;
- for (const auto& type : acceptTypes)
- {
- if ((type.first == "*|*") ||
- (type.first == "application|octet-stream"))
{
- supported = true;
- break;
- }
- }
- if (!supported)
- {
- asyncResp->res.result(boost::beast::http::status::bad_request);
- return;
- }
+ std::string entryID = param;
+ dbus::utility::escapePathForDbus(entryID);
- std::string entryID = params[0];
- dbus::utility::escapePathForDbus(entryID);
+ // DBus implementation of EventLog/Entries
+ // Make call to Logging Service to find all log entry objects
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, entryID](const boost::system::error_code ec,
+ GetManagedPropertyType& resp) {
+ if (ec.value() == EBADR)
+ {
+ messages::resourceNotFound(
+ asyncResp->res, "EventLogEntry", entryID);
+ return;
+ }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "EventLogEntry (DBus) "
+ "resp_handler got error "
+ << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ uint32_t* id = nullptr;
+ std::time_t timestamp{};
+ std::time_t updateTimestamp{};
+ std::string* severity = nullptr;
+ std::string* message = nullptr;
+ std::string* filePath = nullptr;
+ bool resolved = false;
- crow::connections::systemBus->async_method_call(
- [asyncResp, entryID](const boost::system::error_code ec,
- const sdbusplus::message::unix_fd& unixfd) {
- if (ec.value() == EBADR)
+ for (auto& propertyMap : resp)
+ {
+ if (propertyMap.first == "Id")
+ {
+ id = std::get_if<uint32_t>(&propertyMap.second);
+ }
+ else if (propertyMap.first == "Timestamp")
+ {
+ const uint64_t* millisTimeStamp =
+ std::get_if<uint64_t>(&propertyMap.second);
+ if (millisTimeStamp != nullptr)
+ {
+ timestamp = crow::utility::getTimestamp(
+ *millisTimeStamp);
+ }
+ }
+ else if (propertyMap.first == "UpdateTimestamp")
+ {
+ const uint64_t* millisTimeStamp =
+ std::get_if<uint64_t>(&propertyMap.second);
+ if (millisTimeStamp != nullptr)
+ {
+ updateTimestamp =
+ crow::utility::getTimestamp(
+ *millisTimeStamp);
+ }
+ }
+ else if (propertyMap.first == "Severity")
+ {
+ severity = std::get_if<std::string>(
+ &propertyMap.second);
+ }
+ else if (propertyMap.first == "Message")
+ {
+ message = std::get_if<std::string>(
+ &propertyMap.second);
+ }
+ else if (propertyMap.first == "Resolved")
+ {
+ bool* resolveptr =
+ std::get_if<bool>(&propertyMap.second);
+ if (resolveptr == nullptr)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ resolved = *resolveptr;
+ }
+ else if (propertyMap.first == "Path")
+ {
+ filePath = std::get_if<std::string>(
+ &propertyMap.second);
+ }
+ }
+ if (id == nullptr || message == nullptr ||
+ severity == nullptr)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntry.v1_8_0.LogEntry";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/EventLog/"
+ "Entries/" +
+ std::to_string(*id);
+ asyncResp->res.jsonValue["Name"] =
+ "System Event Log Entry";
+ asyncResp->res.jsonValue["Id"] = std::to_string(*id);
+ asyncResp->res.jsonValue["Message"] = *message;
+ asyncResp->res.jsonValue["Resolved"] = resolved;
+ asyncResp->res.jsonValue["EntryType"] = "Event";
+ asyncResp->res.jsonValue["Severity"] =
+ translateSeverityDbusToRedfish(*severity);
+ asyncResp->res.jsonValue["Created"] =
+ crow::utility::getDateTime(timestamp);
+ asyncResp->res.jsonValue["Modified"] =
+ crow::utility::getDateTime(updateTimestamp);
+ if (filePath != nullptr)
+ {
+ asyncResp->res.jsonValue["AdditionalDataURI"] =
+ "/redfish/v1/Systems/system/LogServices/"
+ "EventLog/"
+ "attachment/" +
+ std::to_string(*id);
+ }
+ },
+ "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging/entry/" + entryID,
+ "org.freedesktop.DBus.Properties", "GetAll", "");
+ });
+
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::patch)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& entryId) {
+ std::optional<bool> resolved;
+
+ if (!json_util::readJson(req, asyncResp->res, "Resolved",
+ resolved))
{
- messages::resourceNotFound(asyncResp->res,
- "EventLogAttachment", entryID);
return;
}
- if (ec)
- {
- BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
+ BMCWEB_LOG_DEBUG << "Set Resolved";
- int fd = -1;
- fd = dup(unixfd);
- if (fd == -1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, resolved,
+ entryId](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
+ "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging/entry/" + entryId,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Logging.Entry", "Resolved",
+ std::variant<bool>(*resolved));
+ });
- long long int size = lseek(fd, 0, SEEK_END);
- if (size == -1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::delete_)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param)
- // Arbitrary max size of 64kb
- constexpr int maxFileSize = 65536;
- if (size > maxFileSize)
- {
- BMCWEB_LOG_ERROR
- << "File size exceeds maximum allowed size of "
- << maxFileSize;
- messages::internalError(asyncResp->res);
- return;
- }
- std::vector<char> data(static_cast<size_t>(size));
- long long int rc = lseek(fd, 0, SEEK_SET);
- if (rc == -1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- rc = read(fd, data.data(), data.size());
- if ((rc == -1) || (rc != size))
- {
- messages::internalError(asyncResp->res);
- return;
- }
- close(fd);
+ {
+ BMCWEB_LOG_DEBUG << "Do delete single event entries.";
- std::string_view strData(data.data(), data.size());
- std::string output = crow::utility::base64encode(strData);
+ std::string entryID = param;
- asyncResp->res.addHeader("Content-Type",
- "application/octet-stream");
- asyncResp->res.addHeader("Content-Transfer-Encoding", "Base64");
- asyncResp->res.body() = std::move(output);
- },
- "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging/entry/" + entryID,
- "xyz.openbmc_project.Logging.Entry", "GetEntry");
- }
-};
+ dbus::utility::escapePathForDbus(entryID);
-class BMCLogServiceCollection : public Node
+ // Process response from Logging service.
+ auto respHandler = [asyncResp, entryID](
+ const boost::system::error_code ec) {
+ BMCWEB_LOG_DEBUG
+ << "EventLogEntry (DBus) doDelete callback: Done";
+ if (ec)
+ {
+ if (ec.value() == EBADR)
+ {
+ messages::resourceNotFound(asyncResp->res,
+ "LogEntry", entryID);
+ return;
+ }
+ // TODO Handle for specific error code
+ BMCWEB_LOG_ERROR << "EventLogEntry (DBus) doDelete "
+ "respHandler got error "
+ << ec;
+ asyncResp->res.result(
+ boost::beast::http::status::internal_server_error);
+ return;
+ }
+
+ asyncResp->res.result(boost::beast::http::status::ok);
+ };
+
+ // Make call to Logging service to request Delete Log
+ crow::connections::systemBus->async_method_call(
+ respHandler, "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging/entry/" + entryID,
+ "xyz.openbmc_project.Object.Delete", "Delete");
+ });
+}
+
+inline void requestRoutesDBusEventLogEntryDownload(App& app)
{
- public:
- BMCLogServiceCollection(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/"
+ "<str>/attachment")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param)
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
+ {
+ std::string_view acceptHeader = req.getHeaderValue("Accept");
+ // The iterators in boost/http/rfc7230.hpp end the string if '/'
+ // is found, so replace it with arbitrary character '|' which is
+ // not part of the Accept header syntax.
+ std::string acceptStr = boost::replace_all_copy(
+ std::string(acceptHeader), "/", "|");
+ boost::beast::http::ext_list acceptTypes{acceptStr};
+ bool supported = false;
+ for (const auto& type : acceptTypes)
+ {
+ if ((type.first == "*|*") ||
+ (type.first == "application|octet-stream"))
+ {
+ supported = true;
+ break;
+ }
+ }
+ if (!supported)
+ {
+ asyncResp->res.result(
+ boost::beast::http::status::bad_request);
+ return;
+ }
- // Collections don't include the static data added by SubRoute because
- // it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogServiceCollection.LogServiceCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Managers/bmc/LogServices";
- asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
- asyncResp->res.jsonValue["Description"] =
- "Collection of LogServices for this Manager";
- nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
- logServiceArray = nlohmann::json::array();
+ std::string entryID = param;
+ dbus::utility::escapePathForDbus(entryID);
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp,
+ entryID](const boost::system::error_code ec,
+ const sdbusplus::message::unix_fd& unixfd) {
+ if (ec.value() == EBADR)
+ {
+ messages::resourceNotFound(
+ asyncResp->res, "EventLogAttachment", entryID);
+ return;
+ }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ int fd = -1;
+ fd = dup(unixfd);
+ if (fd == -1)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ long long int size = lseek(fd, 0, SEEK_END);
+ if (size == -1)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ // Arbitrary max size of 64kb
+ constexpr int maxFileSize = 65536;
+ if (size > maxFileSize)
+ {
+ BMCWEB_LOG_ERROR
+ << "File size exceeds maximum allowed size of "
+ << maxFileSize;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ std::vector<char> data(static_cast<size_t>(size));
+ long long int rc = lseek(fd, 0, SEEK_SET);
+ if (rc == -1)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ rc = read(fd, data.data(), data.size());
+ if ((rc == -1) || (rc != size))
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ close(fd);
+
+ std::string_view strData(data.data(), data.size());
+ std::string output =
+ crow::utility::base64encode(strData);
+
+ asyncResp->res.addHeader("Content-Type",
+ "application/octet-stream");
+ asyncResp->res.addHeader("Content-Transfer-Encoding",
+ "Base64");
+ asyncResp->res.body() = std::move(output);
+ },
+ "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging/entry/" + entryID,
+ "xyz.openbmc_project.Logging.Entry", "GetEntry");
+ });
+}
+
+inline void requestRoutesBMCLogServiceCollection(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogServiceCollection.LogServiceCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Managers/bmc/LogServices";
+ asyncResp->res.jsonValue["Name"] =
+ "Open BMC Log Services Collection";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of LogServices for this Manager";
+ nlohmann::json& logServiceArray =
+ asyncResp->res.jsonValue["Members"];
+ logServiceArray = nlohmann::json::array();
#ifdef BMCWEB_ENABLE_REDFISH_DUMP_LOG
- logServiceArray.push_back(
- {{"@odata.id", "/redfish/v1/Managers/bmc/LogServices/Dump"}});
+ logServiceArray.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Managers/bmc/LogServices/Dump"}});
#endif
#ifdef BMCWEB_ENABLE_REDFISH_BMC_JOURNAL
- logServiceArray.push_back(
- {{"@odata.id", "/redfish/v1/Managers/bmc/LogServices/Journal"}});
+ logServiceArray.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Managers/bmc/LogServices/Journal"}});
#endif
- asyncResp->res.jsonValue["Members@odata.count"] =
- logServiceArray.size();
- }
-};
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ logServiceArray.size();
+ });
+}
-class BMCJournalLogService : public Node
+inline void requestRoutesBMCJournalLogService(App& app)
{
- public:
- BMCJournalLogService(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/Journal/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Journal/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogService.v1_1_0.LogService";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Managers/bmc/LogServices/Journal";
- asyncResp->res.jsonValue["Name"] = "Open BMC Journal Log Service";
- asyncResp->res.jsonValue["Description"] = "BMC Journal Log Service";
- asyncResp->res.jsonValue["Id"] = "BMC Journal";
- asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
- asyncResp->res.jsonValue["Entries"] = {
- {"@odata.id",
- "/redfish/v1/Managers/bmc/LogServices/Journal/Entries"}};
- }
-};
+ {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogService.v1_1_0.LogService";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Managers/bmc/LogServices/Journal";
+ asyncResp->res.jsonValue["Name"] =
+ "Open BMC Journal Log Service";
+ asyncResp->res.jsonValue["Description"] =
+ "BMC Journal Log Service";
+ asyncResp->res.jsonValue["Id"] = "BMC Journal";
+ asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+ asyncResp->res.jsonValue["Entries"] = {
+ {"@odata.id",
+ "/redfish/v1/Managers/bmc/LogServices/Journal/Entries"}};
+ });
+}
static int fillBMCJournalLogEntryJson(const std::string& bmcJournalLogEntryID,
sd_journal* journal,
@@ -2020,619 +1912,432 @@
return 0;
}
-class BMCJournalLogEntryCollection : public Node
+inline void requestRoutesBMCJournalLogEntryCollection(App& app)
{
- public:
- BMCJournalLogEntryCollection(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/Journal/Entries/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Journal/Entries/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ static constexpr const long maxEntriesPerPage = 1000;
+ uint64_t skip = 0;
+ uint64_t top = maxEntriesPerPage; // Show max entries by default
+ if (!getSkipParam(asyncResp, req, skip))
+ {
+ return;
+ }
+ if (!getTopParam(asyncResp, req, top))
+ {
+ return;
+ }
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Managers/bmc/LogServices/Journal/Entries";
+ asyncResp->res.jsonValue["Name"] = "Open BMC Journal Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of BMC Journal Entries";
+ nlohmann::json& logEntryArray =
+ asyncResp->res.jsonValue["Members"];
+ logEntryArray = nlohmann::json::array();
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
+ // Go through the journal and use the timestamp to create a
+ // unique ID for each entry
+ sd_journal* journalTmp = nullptr;
+ int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY);
+ if (ret < 0)
+ {
+ BMCWEB_LOG_ERROR << "failed to open journal: "
+ << strerror(-ret);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ std::unique_ptr<sd_journal, decltype(&sd_journal_close)>
+ journal(journalTmp, sd_journal_close);
+ journalTmp = nullptr;
+ uint64_t entryCount = 0;
+ // Reset the unique ID on the first entry
+ bool firstEntry = true;
+ SD_JOURNAL_FOREACH(journal.get())
+ {
+ entryCount++;
+ // Handle paging using skip (number of entries to skip from
+ // the start) and top (number of entries to display)
+ if (entryCount <= skip || entryCount > skip + top)
+ {
+ continue;
+ }
- static constexpr const long maxEntriesPerPage = 1000;
- uint64_t skip = 0;
- uint64_t top = maxEntriesPerPage; // Show max entries by default
- if (!getSkipParam(asyncResp, req, skip))
- {
- return;
- }
- if (!getTopParam(asyncResp, req, top))
- {
- return;
- }
- // Collections don't include the static data added by SubRoute because
- // it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Managers/bmc/LogServices/Journal/Entries";
- asyncResp->res.jsonValue["Name"] = "Open BMC Journal Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of BMC Journal Entries";
- nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
- logEntryArray = nlohmann::json::array();
+ std::string idStr;
+ if (!getUniqueEntryID(journal.get(), idStr, firstEntry))
+ {
+ continue;
+ }
- // Go through the journal and use the timestamp to create a unique ID
- // for each entry
- sd_journal* journalTmp = nullptr;
- int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY);
- if (ret < 0)
- {
- BMCWEB_LOG_ERROR << "failed to open journal: " << strerror(-ret);
- messages::internalError(asyncResp->res);
- return;
- }
- std::unique_ptr<sd_journal, decltype(&sd_journal_close)> journal(
- journalTmp, sd_journal_close);
- journalTmp = nullptr;
- uint64_t entryCount = 0;
- // Reset the unique ID on the first entry
- bool firstEntry = true;
- SD_JOURNAL_FOREACH(journal.get())
- {
- entryCount++;
- // Handle paging using skip (number of entries to skip from the
- // start) and top (number of entries to display)
- if (entryCount <= skip || entryCount > skip + top)
- {
- continue;
- }
+ if (firstEntry)
+ {
+ firstEntry = false;
+ }
- std::string idStr;
- if (!getUniqueEntryID(journal.get(), idStr, firstEntry))
- {
- continue;
- }
+ logEntryArray.push_back({});
+ nlohmann::json& bmcJournalLogEntry = logEntryArray.back();
+ if (fillBMCJournalLogEntryJson(idStr, journal.get(),
+ bmcJournalLogEntry) != 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
+ if (skip + top < entryCount)
+ {
+ asyncResp->res.jsonValue["Members@odata.nextLink"] =
+ "/redfish/v1/Managers/bmc/LogServices/Journal/"
+ "Entries?$skip=" +
+ std::to_string(skip + top);
+ }
+ });
+}
- if (firstEntry)
- {
- firstEntry = false;
- }
-
- logEntryArray.push_back({});
- nlohmann::json& bmcJournalLogEntry = logEntryArray.back();
- if (fillBMCJournalLogEntryJson(idStr, journal.get(),
- bmcJournalLogEntry) != 0)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- }
- asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
- if (skip + top < entryCount)
- {
- asyncResp->res.jsonValue["Members@odata.nextLink"] =
- "/redfish/v1/Managers/bmc/LogServices/Journal/Entries?$skip=" +
- std::to_string(skip + top);
- }
- }
-};
-
-class BMCJournalLogEntry : public Node
+inline void requestRoutesBMCJournalLogEntry(App& app)
{
- public:
- BMCJournalLogEntry(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/Journal/Entries/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Managers/bmc/LogServices/Journal/Entries/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& entryID) {
+ // Convert the unique ID back to a timestamp to find the entry
+ uint64_t ts = 0;
+ uint64_t index = 0;
+ if (!getTimestampFromID(asyncResp, entryID, ts, index))
+ {
+ return;
+ }
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
+ sd_journal* journalTmp = nullptr;
+ int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY);
+ if (ret < 0)
+ {
+ BMCWEB_LOG_ERROR << "failed to open journal: "
+ << strerror(-ret);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ std::unique_ptr<sd_journal, decltype(&sd_journal_close)>
+ journal(journalTmp, sd_journal_close);
+ journalTmp = nullptr;
+ // Go to the timestamp in the log and move to the entry at the
+ // index tracking the unique ID
+ std::string idStr;
+ bool firstEntry = true;
+ ret = sd_journal_seek_realtime_usec(journal.get(), ts);
+ if (ret < 0)
+ {
+ BMCWEB_LOG_ERROR << "failed to seek to an entry in journal"
+ << strerror(-ret);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ for (uint64_t i = 0; i <= index; i++)
+ {
+ sd_journal_next(journal.get());
+ if (!getUniqueEntryID(journal.get(), idStr, firstEntry))
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (firstEntry)
+ {
+ firstEntry = false;
+ }
+ }
+ // Confirm that the entry ID matches what was requested
+ if (idStr != entryID)
+ {
+ messages::resourceMissingAtURI(asyncResp->res, entryID);
+ return;
+ }
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& entryID = params[0];
- // Convert the unique ID back to a timestamp to find the entry
- uint64_t ts = 0;
- uint64_t index = 0;
- if (!getTimestampFromID(asyncResp, entryID, ts, index))
- {
- return;
- }
-
- sd_journal* journalTmp = nullptr;
- int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY);
- if (ret < 0)
- {
- BMCWEB_LOG_ERROR << "failed to open journal: " << strerror(-ret);
- messages::internalError(asyncResp->res);
- return;
- }
- std::unique_ptr<sd_journal, decltype(&sd_journal_close)> journal(
- journalTmp, sd_journal_close);
- journalTmp = nullptr;
- // Go to the timestamp in the log and move to the entry at the index
- // tracking the unique ID
- std::string idStr;
- bool firstEntry = true;
- ret = sd_journal_seek_realtime_usec(journal.get(), ts);
- if (ret < 0)
- {
- BMCWEB_LOG_ERROR << "failed to seek to an entry in journal"
- << strerror(-ret);
- messages::internalError(asyncResp->res);
- return;
- }
- for (uint64_t i = 0; i <= index; i++)
- {
- sd_journal_next(journal.get());
- if (!getUniqueEntryID(journal.get(), idStr, firstEntry))
- {
- messages::internalError(asyncResp->res);
- return;
- }
- if (firstEntry)
- {
- firstEntry = false;
- }
- }
- // Confirm that the entry ID matches what was requested
- if (idStr != entryID)
- {
- messages::resourceMissingAtURI(asyncResp->res, entryID);
- return;
- }
-
- if (fillBMCJournalLogEntryJson(entryID, journal.get(),
- asyncResp->res.jsonValue) != 0)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- }
-};
-
-class BMCDumpService : public Node
-{
- public:
- BMCDumpService(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/Dump/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Managers/bmc/LogServices/Dump";
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogService.v1_2_0.LogService";
- asyncResp->res.jsonValue["Name"] = "Dump LogService";
- asyncResp->res.jsonValue["Description"] = "BMC Dump LogService";
- asyncResp->res.jsonValue["Id"] = "Dump";
- asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
- asyncResp->res.jsonValue["Entries"] = {
- {"@odata.id", "/redfish/v1/Managers/bmc/LogServices/Dump/Entries"}};
- asyncResp->res.jsonValue["Actions"] = {
- {"#LogService.ClearLog",
- {{"target", "/redfish/v1/Managers/bmc/LogServices/Dump/"
- "Actions/LogService.ClearLog"}}},
- {"#LogService.CollectDiagnosticData",
- {{"target", "/redfish/v1/Managers/bmc/LogServices/Dump/"
- "Actions/LogService.CollectDiagnosticData"}}}};
- }
-};
-
-class BMCDumpEntryCollection : public Node
-{
- public:
- BMCDumpEntryCollection(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Managers/bmc/LogServices/Dump/Entries";
- asyncResp->res.jsonValue["Name"] = "BMC Dump Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of BMC Dump Entries";
-
- getDumpEntryCollection(asyncResp, "BMC");
- }
-};
-
-class BMCDumpEntry : public Node
-{
- public:
- BMCDumpEntry(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- getDumpEntryById(asyncResp, params[0], "BMC");
- }
-
- void doDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- deleteDumpEntry(asyncResp, params[0], "bmc");
- }
-};
-
-class BMCDumpCreate : public Node
-{
- public:
- BMCDumpCreate(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/Dump/"
- "Actions/"
- "LogService.CollectDiagnosticData/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- createDump(asyncResp, req, "BMC");
- }
-};
-
-class BMCDumpClear : public Node
-{
- public:
- BMCDumpClear(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/LogServices/Dump/"
- "Actions/"
- "LogService.ClearLog/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- clearDump(asyncResp, "BMC");
- }
-};
-
-class SystemDumpService : public Node
-{
- public:
- SystemDumpService(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Dump/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/Dump";
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogService.v1_2_0.LogService";
- asyncResp->res.jsonValue["Name"] = "Dump LogService";
- asyncResp->res.jsonValue["Description"] = "System Dump LogService";
- asyncResp->res.jsonValue["Id"] = "Dump";
- asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
- asyncResp->res.jsonValue["Entries"] = {
- {"@odata.id",
- "/redfish/v1/Systems/system/LogServices/Dump/Entries"}};
- asyncResp->res.jsonValue["Actions"] = {
- {"#LogService.ClearLog",
- {{"target", "/redfish/v1/Systems/system/LogServices/Dump/Actions/"
- "LogService.ClearLog"}}},
- {"#LogService.CollectDiagnosticData",
- {{"target", "/redfish/v1/Systems/system/LogServices/Dump/Actions/"
- "LogService.CollectDiagnosticData"}}}};
- }
-};
-
-class SystemDumpEntryCollection : public Node
-{
- public:
- SystemDumpEntryCollection(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Dump/Entries/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/Dump/Entries";
- asyncResp->res.jsonValue["Name"] = "System Dump Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of System Dump Entries";
-
- getDumpEntryCollection(asyncResp, "System");
- }
-};
-
-class SystemDumpEntry : public Node
-{
- public:
- SystemDumpEntry(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Dump/Entries/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- getDumpEntryById(asyncResp, params[0], "System");
- }
-
- void doDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- deleteDumpEntry(asyncResp, params[0], "system");
- }
-};
-
-class SystemDumpCreate : public Node
-{
- public:
- SystemDumpCreate(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Dump/"
- "Actions/"
- "LogService.CollectDiagnosticData/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- createDump(asyncResp, req, "System");
- }
-};
-
-class SystemDumpClear : public Node
-{
- public:
- SystemDumpClear(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Dump/"
- "Actions/"
- "LogService.ClearLog/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- clearDump(asyncResp, "System");
- }
-};
-
-class CrashdumpService : public Node
-{
- public:
- CrashdumpService(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Crashdump/")
- {
- // Note: Deviated from redfish privilege registry for GET & HEAD
- // method for security reasons.
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::head, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- // Copy over the static data to include the entries added by SubRoute
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/Crashdump";
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogService.v1_2_0.LogService";
- asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
- asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
- asyncResp->res.jsonValue["Id"] = "Oem Crashdump";
- asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
- asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
- asyncResp->res.jsonValue["Entries"] = {
- {"@odata.id",
- "/redfish/v1/Systems/system/LogServices/Crashdump/Entries"}};
- asyncResp->res.jsonValue["Actions"] = {
- {"#LogService.ClearLog",
- {{"target", "/redfish/v1/Systems/system/LogServices/Crashdump/"
- "Actions/LogService.ClearLog"}}},
- {"#LogService.CollectDiagnosticData",
- {{"target", "/redfish/v1/Systems/system/LogServices/Crashdump/"
- "Actions/LogService.CollectDiagnosticData"}}}};
- }
-};
-
-class CrashdumpClear : public Node
-{
- public:
- CrashdumpClear(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/"
- "LogService.ClearLog/")
- {
- // Note: Deviated from redfish privilege registry for GET & HEAD
- // method for security reasons.
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::head, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
- const std::string&) {
- if (ec)
+ if (fillBMCJournalLogEntryJson(entryID, journal.get(),
+ asyncResp->res.jsonValue) != 0)
{
messages::internalError(asyncResp->res);
return;
}
- messages::success(asyncResp->res);
- },
- crashdumpObject, crashdumpPath, deleteAllInterface, "DeleteAll");
- }
-};
+ });
+}
+
+inline void requestRoutesBMCDumpService(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Managers/bmc/LogServices/Dump";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogService.v1_2_0.LogService";
+ asyncResp->res.jsonValue["Name"] = "Dump LogService";
+ asyncResp->res.jsonValue["Description"] = "BMC Dump LogService";
+ asyncResp->res.jsonValue["Id"] = "Dump";
+ asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+ asyncResp->res.jsonValue["Entries"] = {
+ {"@odata.id",
+ "/redfish/v1/Managers/bmc/LogServices/Dump/Entries"}};
+ asyncResp->res.jsonValue["Actions"] = {
+ {"#LogService.ClearLog",
+ {{"target", "/redfish/v1/Managers/bmc/LogServices/Dump/"
+ "Actions/LogService.ClearLog"}}},
+ {"#LogService.CollectDiagnosticData",
+ {{"target", "/redfish/v1/Managers/bmc/LogServices/Dump/"
+ "Actions/LogService.CollectDiagnosticData"}}}};
+ });
+}
+
+inline void requestRoutesBMCDumpEntryCollection(App& app)
+{
+
+ /**
+ * Functions triggers appropriate requests on DBus
+ */
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Managers/bmc/LogServices/Dump/Entries";
+ asyncResp->res.jsonValue["Name"] = "BMC Dump Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of BMC Dump Entries";
+
+ getDumpEntryCollection(asyncResp, "BMC");
+ });
+}
+
+inline void requestRoutesBMCDumpEntry(App& app)
+{
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ getDumpEntryById(asyncResp, param, "BMC");
+ });
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/<str>/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::delete_)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ deleteDumpEntry(asyncResp, param, "bmc");
+ });
+}
+
+inline void requestRoutesBMCDumpCreate(App& app)
+{
+
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/"
+ "Actions/"
+ "LogService.CollectDiagnosticData/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ createDump(asyncResp, req, "BMC");
+ });
+}
+
+inline void requestRoutesBMCDumpClear(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/"
+ "Actions/"
+ "LogService.ClearLog/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ clearDump(asyncResp, "BMC");
+ });
+}
+
+inline void requestRoutesSystemDumpService(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Dump/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+
+ {
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/Dump";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogService.v1_2_0.LogService";
+ asyncResp->res.jsonValue["Name"] = "Dump LogService";
+ asyncResp->res.jsonValue["Description"] =
+ "System Dump LogService";
+ asyncResp->res.jsonValue["Id"] = "Dump";
+ asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+ asyncResp->res.jsonValue["Entries"] = {
+ {"@odata.id",
+ "/redfish/v1/Systems/system/LogServices/Dump/Entries"}};
+ asyncResp->res.jsonValue["Actions"] = {
+ {"#LogService.ClearLog",
+ {{"target",
+ "/redfish/v1/Systems/system/LogServices/Dump/Actions/"
+ "LogService.ClearLog"}}},
+ {"#LogService.CollectDiagnosticData",
+ {{"target",
+ "/redfish/v1/Systems/system/LogServices/Dump/Actions/"
+ "LogService.CollectDiagnosticData"}}}};
+ });
+}
+
+inline void requestRoutesSystemDumpEntryCollection(App& app)
+{
+
+ /**
+ * Functions triggers appropriate requests on DBus
+ */
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string&) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/Dump/Entries";
+ asyncResp->res.jsonValue["Name"] = "System Dump Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of System Dump Entries";
+
+ getDumpEntryCollection(asyncResp, "System");
+ });
+}
+
+inline void requestRoutesSystemDumpEntry(App& app)
+{
+ BMCWEB_ROUTE(app,
+ "redfish/v1/Systems/system/LogServices/Dump/Entries/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ getDumpEntryById(asyncResp, param, "System");
+ });
+
+ BMCWEB_ROUTE(app,
+ "redfish/v1/Systems/system/LogServices/Dump/Entries/<str>/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::delete_)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ deleteDumpEntry(asyncResp, param, "system");
+ });
+}
+
+inline void requestRoutesSystemDumpCreate(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Dump/"
+ "Actions/"
+ "LogService.CollectDiagnosticData/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+
+ { createDump(asyncResp, req, "System"); });
+}
+
+inline void requestRoutesSystemDumpClear(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Dump/"
+ "Actions/"
+ "LogService.ClearLog/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+
+ { clearDump(asyncResp, "System"); });
+}
+
+inline void requestRoutesCrashdumpService(App& app)
+{
+ // Note: Deviated from redfish privilege registry for GET & HEAD
+ // method for security reasons.
+ /**
+ * Functions triggers appropriate requests on DBus
+ */
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Crashdump/")
+ .privileges({"ConfigureManager"})
+ .methods(
+ boost::beast::http::verb::
+ get)([](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ // Copy over the static data to include the entries added by
+ // SubRoute
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/Crashdump";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogService.v1_2_0.LogService";
+ asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
+ asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
+ asyncResp->res.jsonValue["Id"] = "Oem Crashdump";
+ asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+ asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
+ asyncResp->res.jsonValue["Entries"] = {
+ {"@odata.id",
+ "/redfish/v1/Systems/system/LogServices/Crashdump/Entries"}};
+ asyncResp->res.jsonValue["Actions"] = {
+ {"#LogService.ClearLog",
+ {{"target", "/redfish/v1/Systems/system/LogServices/Crashdump/"
+ "Actions/LogService.ClearLog"}}},
+ {"#LogService.CollectDiagnosticData",
+ {{"target", "/redfish/v1/Systems/system/LogServices/Crashdump/"
+ "Actions/LogService.CollectDiagnosticData"}}}};
+ });
+}
+
+void inline requestRoutesCrashdumpClear(App& app)
+{
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/"
+ "LogService.ClearLog/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec,
+ const std::string&) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ messages::success(asyncResp->res);
+ },
+ crashdumpObject, crashdumpPath, deleteAllInterface,
+ "DeleteAll");
+ });
+}
static void
logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -2690,474 +2395,396 @@
"org.freedesktop.DBus.Properties", "GetAll", crashdumpInterface);
}
-class CrashdumpEntryCollection : public Node
+inline void requestRoutesCrashdumpEntryCollection(App& app)
{
- public:
- CrashdumpEntryCollection(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/")
- {
- // Note: Deviated from redfish privilege registry for GET & HEAD
- // method for security reasons.
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::head, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
+ // Note: Deviated from redfish privilege registry for GET & HEAD
+ // method for security reasons.
/**
* Functions triggers appropriate requests on DBus
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- // Collections don't include the static data added by SubRoute because
- // it has a duplicate entry for members
- auto getLogEntriesCallback = [asyncResp](
- const boost::system::error_code ec,
- const std::vector<std::string>& resp) {
- if (ec)
- {
- if (ec.value() !=
- boost::system::errc::no_such_file_or_directory)
- {
- BMCWEB_LOG_DEBUG << "failed to get entries ec: "
- << ec.message();
- messages::internalError(asyncResp->res);
- return;
- }
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/Crashdump/Entries";
- asyncResp->res.jsonValue["Name"] = "Open BMC Crashdump Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of Crashdump Entries";
- nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
- logEntryArray = nlohmann::json::array();
- std::vector<std::string> logIDs;
- // Get the list of log entries and build up an empty array big
- // enough to hold them
- for (const std::string& objpath : resp)
- {
- // Get the log ID
- std::size_t lastPos = objpath.rfind('/');
- if (lastPos == std::string::npos)
- {
- continue;
- }
- logIDs.emplace_back(objpath.substr(lastPos + 1));
-
- // Add a space for the log entry to the array
- logEntryArray.push_back({});
- }
- // Now go through and set up async calls to fill in the entries
- size_t index = 0;
- for (const std::string& logID : logIDs)
- {
- // Add the log entry to the array
- logCrashdumpEntry(asyncResp, logID, logEntryArray[index++]);
- }
- asyncResp->res.jsonValue["Members@odata.count"] =
- logEntryArray.size();
- };
- crow::connections::systemBus->async_method_call(
- std::move(getLogEntriesCallback),
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "", 0,
- std::array<const char*, 1>{crashdumpInterface});
- }
-};
-
-class CrashdumpEntry : public Node
-{
- public:
- CrashdumpEntry(App& app) :
- Node(app,
- "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/<str>/",
- std::string())
- {
- // Note: Deviated from redfish privilege registry for GET & HEAD
- // method for security reasons.
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::head, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& logID = params[0];
- logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
- }
-};
-
-class CrashdumpFile : public Node
-{
- public:
- CrashdumpFile(App& app) :
- Node(app,
- "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/<str>/"
- "<str>/",
- std::string(), std::string())
- {
- // Note: Deviated from redfish privilege registry for GET & HEAD
- // method for security reasons.
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::head, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 2)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& logID = params[0];
- const std::string& fileName = params[1];
-
- auto getStoredLogCallback =
- [asyncResp, logID, fileName](
- const boost::system::error_code ec,
- const std::vector<std::pair<std::string, VariantType>>& resp) {
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/")
+ .privileges({"ConfigureComponents"})
+ .methods(
+ boost::beast::http::verb::
+ get)([](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ auto getLogEntriesCallback = [asyncResp](
+ const boost::system::error_code ec,
+ const std::vector<std::string>&
+ resp) {
if (ec)
{
- BMCWEB_LOG_DEBUG << "failed to get log ec: "
- << ec.message();
- messages::internalError(asyncResp->res);
- return;
+ if (ec.value() !=
+ boost::system::errc::no_such_file_or_directory)
+ {
+ BMCWEB_LOG_DEBUG << "failed to get entries ec: "
+ << ec.message();
+ messages::internalError(asyncResp->res);
+ return;
+ }
}
-
- std::string dbusFilename{};
- std::string dbusTimestamp{};
- std::string dbusFilepath{};
-
- parseCrashdumpParameters(resp, dbusFilename, dbusTimestamp,
- dbusFilepath);
-
- if (dbusFilename.empty() || dbusTimestamp.empty() ||
- dbusFilepath.empty())
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/Crashdump/Entries";
+ asyncResp->res.jsonValue["Name"] = "Open BMC Crashdump Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of Crashdump Entries";
+ nlohmann::json& logEntryArray =
+ asyncResp->res.jsonValue["Members"];
+ logEntryArray = nlohmann::json::array();
+ std::vector<std::string> logIDs;
+ // Get the list of log entries and build up an empty array big
+ // enough to hold them
+ for (const std::string& objpath : resp)
{
- messages::resourceMissingAtURI(asyncResp->res, fileName);
- return;
- }
+ // Get the log ID
+ std::size_t lastPos = objpath.rfind('/');
+ if (lastPos == std::string::npos)
+ {
+ continue;
+ }
+ logIDs.emplace_back(objpath.substr(lastPos + 1));
- // Verify the file name parameter is correct
- if (fileName != dbusFilename)
+ // Add a space for the log entry to the array
+ logEntryArray.push_back({});
+ }
+ // Now go through and set up async calls to fill in the entries
+ size_t index = 0;
+ for (const std::string& logID : logIDs)
{
- messages::resourceMissingAtURI(asyncResp->res, fileName);
- return;
+ // Add the log entry to the array
+ logCrashdumpEntry(asyncResp, logID, logEntryArray[index++]);
}
-
- if (!std::filesystem::exists(dbusFilepath))
- {
- messages::resourceMissingAtURI(asyncResp->res, fileName);
- return;
- }
- std::ifstream ifs(dbusFilepath, std::ios::in |
- std::ios::binary |
- std::ios::ate);
- std::ifstream::pos_type fileSize = ifs.tellg();
- if (fileSize < 0)
- {
- messages::generalError(asyncResp->res);
- return;
- }
- ifs.seekg(0, std::ios::beg);
-
- auto crashData = std::make_unique<char[]>(
- static_cast<unsigned int>(fileSize));
-
- ifs.read(crashData.get(), static_cast<int>(fileSize));
-
- // The cast to std::string is intentional in order to use the
- // assign() that applies move mechanics
- asyncResp->res.body().assign(
- static_cast<std::string>(crashData.get()));
-
- // Configure this to be a file download when accessed from
- // a browser
- asyncResp->res.addHeader("Content-Disposition", "attachment");
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ logEntryArray.size();
};
- crow::connections::systemBus->async_method_call(
- std::move(getStoredLogCallback), crashdumpObject,
- crashdumpPath + std::string("/") + logID,
- "org.freedesktop.DBus.Properties", "GetAll", crashdumpInterface);
- }
-};
+ crow::connections::systemBus->async_method_call(
+ std::move(getLogEntriesCallback),
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "", 0,
+ std::array<const char*, 1>{crashdumpInterface});
+ });
+}
-class CrashdumpCollect : public Node
+inline void requestRoutesCrashdumpEntry(App& app)
{
- public:
- CrashdumpCollect(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/"
- "LogService.CollectDiagnosticData/")
- {
- // Note: Deviated from redfish privilege registry for GET & HEAD
- // method for security reasons.
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::head, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ // Note: Deviated from redfish privilege registry for GET & HEAD
+ // method for security reasons.
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/<str>/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ const std::string& logID = param;
+ logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
+ });
+}
- std::string diagnosticDataType;
- std::string oemDiagnosticDataType;
- if (!redfish::json_util::readJson(
- req, asyncResp->res, "DiagnosticDataType", diagnosticDataType,
- "OEMDiagnosticDataType", oemDiagnosticDataType))
- {
- return;
- }
+inline void requestRoutesCrashdumpFile(App& app)
+{
+ // Note: Deviated from redfish privilege registry for GET & HEAD
+ // method for security reasons.
+ BMCWEB_ROUTE(
+ app,
+ "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/<str>/<str>/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& logID, const std::string& fileName) {
+ auto getStoredLogCallback =
+ [asyncResp, logID, fileName](
+ const boost::system::error_code ec,
+ const std::vector<std::pair<std::string, VariantType>>&
+ resp) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "failed to get log ec: "
+ << ec.message();
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (diagnosticDataType != "OEM")
- {
- BMCWEB_LOG_ERROR
- << "Only OEM DiagnosticDataType supported for Crashdump";
- messages::actionParameterValueFormatError(
- asyncResp->res, diagnosticDataType, "DiagnosticDataType",
- "CollectDiagnosticData");
- return;
- }
+ std::string dbusFilename{};
+ std::string dbusTimestamp{};
+ std::string dbusFilepath{};
- auto collectCrashdumpCallback = [asyncResp, req](
- const boost::system::error_code ec,
- const std::string&) {
- if (ec)
+ parseCrashdumpParameters(resp, dbusFilename,
+ dbusTimestamp, dbusFilepath);
+
+ if (dbusFilename.empty() || dbusTimestamp.empty() ||
+ dbusFilepath.empty())
+ {
+ messages::resourceMissingAtURI(asyncResp->res,
+ fileName);
+ return;
+ }
+
+ // Verify the file name parameter is correct
+ if (fileName != dbusFilename)
+ {
+ messages::resourceMissingAtURI(asyncResp->res,
+ fileName);
+ return;
+ }
+
+ if (!std::filesystem::exists(dbusFilepath))
+ {
+ messages::resourceMissingAtURI(asyncResp->res,
+ fileName);
+ return;
+ }
+ std::ifstream ifs(dbusFilepath, std::ios::in |
+ std::ios::binary |
+ std::ios::ate);
+ std::ifstream::pos_type fileSize = ifs.tellg();
+ if (fileSize < 0)
+ {
+ messages::generalError(asyncResp->res);
+ return;
+ }
+ ifs.seekg(0, std::ios::beg);
+
+ auto crashData = std::make_unique<char[]>(
+ static_cast<unsigned int>(fileSize));
+
+ ifs.read(crashData.get(), static_cast<int>(fileSize));
+
+ // The cast to std::string is intentional in order to
+ // use the assign() that applies move mechanics
+ asyncResp->res.body().assign(
+ static_cast<std::string>(crashData.get()));
+
+ // Configure this to be a file download when accessed
+ // from a browser
+ asyncResp->res.addHeader("Content-Disposition",
+ "attachment");
+ };
+ crow::connections::systemBus->async_method_call(
+ std::move(getStoredLogCallback), crashdumpObject,
+ crashdumpPath + std::string("/") + logID,
+ "org.freedesktop.DBus.Properties", "GetAll",
+ crashdumpInterface);
+ });
+}
+
+inline void requestRoutesCrashdumpCollect(App& app)
+{
+ // Note: Deviated from redfish privilege registry for GET & HEAD
+ // method for security reasons.
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Crashdump/"
+ "Actions/LogService.CollectDiagnosticData/")
+ .privileges({"ConfigureComponents"})
+ .methods(
+ boost::beast::http::verb::
+ post)([](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ std::string diagnosticDataType;
+ std::string oemDiagnosticDataType;
+ if (!redfish::json_util::readJson(
+ req, asyncResp->res, "DiagnosticDataType",
+ diagnosticDataType, "OEMDiagnosticDataType",
+ oemDiagnosticDataType))
{
- if (ec.value() == boost::system::errc::operation_not_supported)
- {
- messages::resourceInStandby(asyncResp->res);
- }
- else if (ec.value() ==
- boost::system::errc::device_or_resource_busy)
- {
- messages::serviceTemporarilyUnavailable(asyncResp->res,
- "60");
- }
- else
- {
- messages::internalError(asyncResp->res);
- }
return;
}
- std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
- [](boost::system::error_code err, sdbusplus::message::message&,
- const std::shared_ptr<task::TaskData>& taskData) {
- if (!err)
- {
- taskData->messages.emplace_back(
- messages::taskCompletedOK(
- std::to_string(taskData->index)));
- taskData->state = "Completed";
- }
- return task::completed;
- },
- "type='signal',interface='org.freedesktop.DBus.Properties',"
- "member='PropertiesChanged',arg0namespace='com.intel."
- "crashdump'");
- task->startTimer(std::chrono::minutes(5));
- task->populateResp(asyncResp->res);
- task->payload.emplace(req);
- };
- if (oemDiagnosticDataType == "OnDemand")
- {
- crow::connections::systemBus->async_method_call(
- std::move(collectCrashdumpCallback), crashdumpObject,
- crashdumpPath, crashdumpOnDemandInterface,
- "GenerateOnDemandLog");
- }
- else if (oemDiagnosticDataType == "Telemetry")
- {
- crow::connections::systemBus->async_method_call(
- std::move(collectCrashdumpCallback), crashdumpObject,
- crashdumpPath, crashdumpTelemetryInterface,
- "GenerateTelemetryLog");
- }
- else
- {
- BMCWEB_LOG_ERROR << "Unsupported OEMDiagnosticDataType: "
- << oemDiagnosticDataType;
- messages::actionParameterValueFormatError(
- asyncResp->res, oemDiagnosticDataType, "OEMDiagnosticDataType",
- "CollectDiagnosticData");
- return;
- }
- }
-};
+ if (diagnosticDataType != "OEM")
+ {
+ BMCWEB_LOG_ERROR
+ << "Only OEM DiagnosticDataType supported for Crashdump";
+ messages::actionParameterValueFormatError(
+ asyncResp->res, diagnosticDataType, "DiagnosticDataType",
+ "CollectDiagnosticData");
+ return;
+ }
+
+ auto collectCrashdumpCallback = [asyncResp, req](
+ const boost::system::error_code
+ ec,
+ const std::string&) {
+ if (ec)
+ {
+ if (ec.value() ==
+ boost::system::errc::operation_not_supported)
+ {
+ messages::resourceInStandby(asyncResp->res);
+ }
+ else if (ec.value() ==
+ boost::system::errc::device_or_resource_busy)
+ {
+ messages::serviceTemporarilyUnavailable(asyncResp->res,
+ "60");
+ }
+ else
+ {
+ messages::internalError(asyncResp->res);
+ }
+ return;
+ }
+ std::shared_ptr<task::TaskData> task =
+ task::TaskData::createTask(
+ [](boost::system::error_code err,
+ sdbusplus::message::message&,
+ const std::shared_ptr<task::TaskData>& taskData) {
+ if (!err)
+ {
+ taskData->messages.emplace_back(
+ messages::taskCompletedOK(
+ std::to_string(taskData->index)));
+ taskData->state = "Completed";
+ }
+ return task::completed;
+ },
+ "type='signal',interface='org.freedesktop.DBus."
+ "Properties',"
+ "member='PropertiesChanged',arg0namespace='com.intel."
+ "crashdump'");
+ task->startTimer(std::chrono::minutes(5));
+ task->populateResp(asyncResp->res);
+ task->payload.emplace(req);
+ };
+
+ if (oemDiagnosticDataType == "OnDemand")
+ {
+ crow::connections::systemBus->async_method_call(
+ std::move(collectCrashdumpCallback), crashdumpObject,
+ crashdumpPath, crashdumpOnDemandInterface,
+ "GenerateOnDemandLog");
+ }
+ else if (oemDiagnosticDataType == "Telemetry")
+ {
+ crow::connections::systemBus->async_method_call(
+ std::move(collectCrashdumpCallback), crashdumpObject,
+ crashdumpPath, crashdumpTelemetryInterface,
+ "GenerateTelemetryLog");
+ }
+ else
+ {
+ BMCWEB_LOG_ERROR << "Unsupported OEMDiagnosticDataType: "
+ << oemDiagnosticDataType;
+ messages::actionParameterValueFormatError(
+ asyncResp->res, oemDiagnosticDataType,
+ "OEMDiagnosticDataType", "CollectDiagnosticData");
+ return;
+ }
+ });
+}
/**
* DBusLogServiceActionsClear class supports POST method for ClearLog action.
*/
-class DBusLogServiceActionsClear : public Node
+inline void requestRoutesDBusLogServiceActionsClear(App& app)
{
- public:
- DBusLogServiceActionsClear(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/EventLog/Actions/"
- "LogService.ClearLog/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
/**
* Function handles POST method request.
* The Clear Log actions does not require any parameter.The action deletes
* all entries found in the Entries collection for this Log Service.
*/
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- BMCWEB_LOG_DEBUG << "Do delete all entries.";
- // Process response from Logging service.
- auto respHandler = [asyncResp](const boost::system::error_code ec) {
- BMCWEB_LOG_DEBUG << "doClearLog resp_handler callback: Done";
- if (ec)
- {
- // TODO Handle for specific error code
- BMCWEB_LOG_ERROR << "doClearLog resp_handler got error " << ec;
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/EventLog/Actions/"
+ "LogService.ClearLog/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ BMCWEB_LOG_DEBUG << "Do delete all entries.";
- asyncResp->res.result(boost::beast::http::status::no_content);
- };
+ // Process response from Logging service.
+ auto respHandler = [asyncResp](
+ const boost::system::error_code ec) {
+ BMCWEB_LOG_DEBUG
+ << "doClearLog resp_handler callback: Done";
+ if (ec)
+ {
+ // TODO Handle for specific error code
+ BMCWEB_LOG_ERROR << "doClearLog resp_handler got error "
+ << ec;
+ asyncResp->res.result(
+ boost::beast::http::status::internal_server_error);
+ return;
+ }
- // Make call to Logging service to request Clear Log
- crow::connections::systemBus->async_method_call(
- respHandler, "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging",
- "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
- }
-};
+ asyncResp->res.result(
+ boost::beast::http::status::no_content);
+ };
+
+ // Make call to Logging service to request Clear Log
+ crow::connections::systemBus->async_method_call(
+ respHandler, "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging",
+ "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
+ });
+}
/****************************************************
* Redfish PostCode interfaces
* using DBUS interface: getPostCodesTS
******************************************************/
-class PostCodesLogService : public Node
+inline void requestRoutesPostCodesLogService(App& app)
{
- public:
- PostCodesLogService(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/PostCodes/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/PostCodes/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue = {
+ {"@odata.id",
+ "/redfish/v1/Systems/system/LogServices/PostCodes"},
+ {"@odata.type", "#LogService.v1_1_0.LogService"},
+ {"Name", "POST Code Log Service"},
+ {"Description", "POST Code Log Service"},
+ {"Id", "BIOS POST Code Log"},
+ {"OverWritePolicy", "WrapsWhenFull"},
+ {"Entries",
+ {{"@odata.id", "/redfish/v1/Systems/system/LogServices/"
+ "PostCodes/Entries"}}}};
+ asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = {
+ {"target",
+ "/redfish/v1/Systems/system/LogServices/PostCodes/"
+ "Actions/LogService.ClearLog"}};
+ });
+}
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- asyncResp->res.jsonValue = {
- {"@odata.id", "/redfish/v1/Systems/system/LogServices/PostCodes"},
- {"@odata.type", "#LogService.v1_1_0.LogService"},
- {"Name", "POST Code Log Service"},
- {"Description", "POST Code Log Service"},
- {"Id", "BIOS POST Code Log"},
- {"OverWritePolicy", "WrapsWhenFull"},
- {"Entries",
- {{"@odata.id",
- "/redfish/v1/Systems/system/LogServices/PostCodes/Entries"}}}};
- asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = {
- {"target", "/redfish/v1/Systems/system/LogServices/PostCodes/"
- "Actions/LogService.ClearLog"}};
- }
-};
-
-class PostCodesClear : public Node
+inline void requestRoutesPostCodesClear(App& app)
{
- public:
- PostCodesClear(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/PostCodes/Actions/"
- "LogService.ClearLog/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/system/LogServices/PostCodes/Actions/"
+ "LogService.ClearLog/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ BMCWEB_LOG_DEBUG << "Do delete all postcodes entries.";
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- BMCWEB_LOG_DEBUG << "Do delete all postcodes entries.";
-
- // Make call to post-code service to request clear all
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec) {
- if (ec)
- {
- // TODO Handle for specific error code
- BMCWEB_LOG_ERROR
- << "doClearPostCodes resp_handler got error " << ec;
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- messages::internalError(asyncResp->res);
- return;
- }
- },
- "xyz.openbmc_project.State.Boot.PostCode0",
- "/xyz/openbmc_project/State/Boot/PostCode0",
- "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
- }
-};
+ // Make call to post-code service to request clear all
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ // TODO Handle for specific error code
+ BMCWEB_LOG_ERROR
+ << "doClearPostCodes resp_handler got error "
+ << ec;
+ asyncResp->res.result(boost::beast::http::status::
+ internal_server_error);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
+ "xyz.openbmc_project.State.Boot.PostCode0",
+ "/xyz/openbmc_project/State/Boot/PostCode0",
+ "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
+ });
+}
static void fillPostCodeEntry(
const std::shared_ptr<bmcweb::AsyncResp>& aResp,
@@ -3400,124 +3027,91 @@
"xyz.openbmc_project.State.Boot.PostCode", "CurrentBootCycleCount");
}
-class PostCodesEntryCollection : public Node
+inline void requestRoutesPostCodesEntryCollection(App& app)
{
- public:
- PostCodesEntryCollection(App& app) :
- Node(app, "/redfish/v1/Systems/system/LogServices/PostCodes/Entries/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/system/LogServices/PostCodes/Entries/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/PostCodes/Entries";
+ asyncResp->res.jsonValue["Name"] = "BIOS POST Code Log Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of POST Code Log Entries";
+ asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
+ asyncResp->res.jsonValue["Members@odata.count"] = 0;
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
+ uint64_t skip = 0;
+ uint64_t top = maxEntriesPerPage; // Show max entries by default
+ if (!getSkipParam(asyncResp, req, skip))
+ {
+ return;
+ }
+ if (!getTopParam(asyncResp, req, top))
+ {
+ return;
+ }
+ getCurrentBootNumber(asyncResp, skip, top);
+ });
+}
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/PostCodes/Entries";
- asyncResp->res.jsonValue["Name"] = "BIOS POST Code Log Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of POST Code Log Entries";
- asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
- asyncResp->res.jsonValue["Members@odata.count"] = 0;
-
- uint64_t skip = 0;
- uint64_t top = maxEntriesPerPage; // Show max entries by default
- if (!getSkipParam(asyncResp, req, skip))
- {
- return;
- }
- if (!getTopParam(asyncResp, req, top))
- {
- return;
- }
- getCurrentBootNumber(asyncResp, skip, top);
- }
-};
-
-class PostCodesEntry : public Node
+inline void requestRoutesPostCodesEntry(App& app)
{
- public:
- PostCodesEntry(App& app) :
- Node(app,
- "/redfish/v1/Systems/system/LogServices/PostCodes/Entries/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/system/LogServices/PostCodes/Entries/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& targetID) {
+ size_t bootPos = targetID.find('B');
+ if (bootPos == std::string::npos)
+ {
+ // Requested ID was not found
+ messages::resourceMissingAtURI(asyncResp->res, targetID);
+ return;
+ }
+ std::string_view bootIndexStr(targetID);
+ bootIndexStr.remove_prefix(bootPos + 1);
+ uint16_t bootIndex = 0;
+ uint64_t codeIndex = 0;
+ size_t dashPos = bootIndexStr.find('-');
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
+ if (dashPos == std::string::npos)
+ {
+ return;
+ }
+ std::string_view codeIndexStr(bootIndexStr);
+ bootIndexStr.remove_suffix(dashPos);
+ codeIndexStr.remove_prefix(dashPos + 1);
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ bootIndex = static_cast<uint16_t>(
+ strtoul(std::string(bootIndexStr).c_str(), nullptr, 0));
+ codeIndex =
+ strtoul(std::string(codeIndexStr).c_str(), nullptr, 0);
+ if (bootIndex == 0 || codeIndex == 0)
+ {
+ BMCWEB_LOG_DEBUG << "Get Post Code invalid entry string "
+ << targetID;
+ }
- const std::string& targetID = params[0];
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntry.v1_4_0.LogEntry";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/PostCodes/"
+ "Entries";
+ asyncResp->res.jsonValue["Name"] = "BIOS POST Code Log Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of POST Code Log Entries";
+ asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
+ asyncResp->res.jsonValue["Members@odata.count"] = 0;
- size_t bootPos = targetID.find('B');
- if (bootPos == std::string::npos)
- {
- // Requested ID was not found
- messages::resourceMissingAtURI(asyncResp->res, targetID);
- return;
- }
- std::string_view bootIndexStr(targetID);
- bootIndexStr.remove_prefix(bootPos + 1);
- uint16_t bootIndex = 0;
- uint64_t codeIndex = 0;
- size_t dashPos = bootIndexStr.find('-');
-
- if (dashPos == std::string::npos)
- {
- return;
- }
- std::string_view codeIndexStr(bootIndexStr);
- bootIndexStr.remove_suffix(dashPos);
- codeIndexStr.remove_prefix(dashPos + 1);
-
- bootIndex = static_cast<uint16_t>(
- strtoul(std::string(bootIndexStr).c_str(), nullptr, 0));
- codeIndex = strtoul(std::string(codeIndexStr).c_str(), nullptr, 0);
- if (bootIndex == 0 || codeIndex == 0)
- {
- BMCWEB_LOG_DEBUG << "Get Post Code invalid entry string "
- << params[0];
- }
-
- asyncResp->res.jsonValue["@odata.type"] = "#LogEntry.v1_4_0.LogEntry";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/PostCodes/"
- "Entries";
- asyncResp->res.jsonValue["Name"] = "BIOS POST Code Log Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of POST Code Log Entries";
- asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
- asyncResp->res.jsonValue["Members@odata.count"] = 0;
-
- getPostCodeForEntry(asyncResp, bootIndex, codeIndex);
- }
-};
+ getPostCodeForEntry(asyncResp, bootIndex, codeIndex);
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index 67f8d99..a92f490 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -16,9 +16,9 @@
#pragma once
#include "health.hpp"
-#include "node.hpp"
#include "redfish_util.hpp"
+#include <app.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/date_time.hpp>
#include <dbus_utility.hpp>
@@ -100,71 +100,57 @@
* ManagerResetAction class supports the POST method for the Reset (reboot)
* action.
*/
-class ManagerResetAction : public Node
+inline void requestRoutesManagerResetAction(App& app)
{
- public:
- ManagerResetAction(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/Actions/Manager.Reset/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
/**
* Function handles POST method request.
* Analyzes POST body before sending Reset (Reboot) request data to D-Bus.
* OpenBMC supports ResetType "GracefulRestart" and "ForceRestart".
*/
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- BMCWEB_LOG_DEBUG << "Post Manager Reset.";
- std::string resetType;
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Actions/Manager.Reset/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ BMCWEB_LOG_DEBUG << "Post Manager Reset.";
- if (!json_util::readJson(req, asyncResp->res, "ResetType", resetType))
- {
- return;
- }
+ std::string resetType;
- if (resetType == "GracefulRestart")
- {
- BMCWEB_LOG_DEBUG << "Proceeding with " << resetType;
- doBMCGracefulRestart(asyncResp);
- return;
- }
- if (resetType == "ForceRestart")
- {
- BMCWEB_LOG_DEBUG << "Proceeding with " << resetType;
- doBMCForceRestart(asyncResp);
- return;
- }
- BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
- << resetType;
- messages::actionParameterNotSupported(asyncResp->res, resetType,
- "ResetType");
+ if (!json_util::readJson(req, asyncResp->res, "ResetType",
+ resetType))
+ {
+ return;
+ }
- return;
- }
-};
+ if (resetType == "GracefulRestart")
+ {
+ BMCWEB_LOG_DEBUG << "Proceeding with " << resetType;
+ doBMCGracefulRestart(asyncResp);
+ return;
+ }
+ if (resetType == "ForceRestart")
+ {
+ BMCWEB_LOG_DEBUG << "Proceeding with " << resetType;
+ doBMCForceRestart(asyncResp);
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
+ << resetType;
+ messages::actionParameterNotSupported(asyncResp->res, resetType,
+ "ResetType");
+
+ return;
+ });
+}
/**
* ManagerResetToDefaultsAction class supports POST method for factory reset
* action.
*/
-class ManagerResetToDefaultsAction : public Node
+inline void requestRoutesManagerResetToDefaultsAction(App& app)
{
- public:
- ManagerResetToDefaultsAction(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/Actions/Manager.ResetToDefaults/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
- private:
/**
* Function handles ResetToDefaults POST method request.
*
@@ -176,93 +162,85 @@
*
* OpenBMC only supports ResetToDefaultsType "ResetAll".
*/
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- BMCWEB_LOG_DEBUG << "Post ResetToDefaults.";
- std::string resetType;
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Managers/bmc/Actions/Manager.ResetToDefaults/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ BMCWEB_LOG_DEBUG << "Post ResetToDefaults.";
- if (!json_util::readJson(req, asyncResp->res, "ResetToDefaultsType",
- resetType))
- {
- BMCWEB_LOG_DEBUG << "Missing property ResetToDefaultsType.";
+ std::string resetType;
- messages::actionParameterMissing(asyncResp->res, "ResetToDefaults",
- "ResetToDefaultsType");
- return;
- }
-
- if (resetType != "ResetAll")
- {
- BMCWEB_LOG_DEBUG << "Invalid property value for "
- "ResetToDefaultsType: "
- << resetType;
- messages::actionParameterNotSupported(asyncResp->res, resetType,
- "ResetToDefaultsType");
- return;
- }
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec) {
- if (ec)
+ if (!json_util::readJson(req, asyncResp->res,
+ "ResetToDefaultsType", resetType))
{
- BMCWEB_LOG_DEBUG << "Failed to ResetToDefaults: " << ec;
- messages::internalError(asyncResp->res);
+ BMCWEB_LOG_DEBUG << "Missing property ResetToDefaultsType.";
+
+ messages::actionParameterMissing(asyncResp->res,
+ "ResetToDefaults",
+ "ResetToDefaultsType");
return;
}
- // Factory Reset doesn't actually happen until a reboot
- // Can't erase what the BMC is running on
- doBMCGracefulRestart(asyncResp);
- },
- "xyz.openbmc_project.Software.BMC.Updater",
- "/xyz/openbmc_project/software",
- "xyz.openbmc_project.Common.FactoryReset", "Reset");
- }
-};
+
+ if (resetType != "ResetAll")
+ {
+ BMCWEB_LOG_DEBUG << "Invalid property value for "
+ "ResetToDefaultsType: "
+ << resetType;
+ messages::actionParameterNotSupported(
+ asyncResp->res, resetType, "ResetToDefaultsType");
+ return;
+ }
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "Failed to ResetToDefaults: "
+ << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ // Factory Reset doesn't actually happen until a reboot
+ // Can't erase what the BMC is running on
+ doBMCGracefulRestart(asyncResp);
+ },
+ "xyz.openbmc_project.Software.BMC.Updater",
+ "/xyz/openbmc_project/software",
+ "xyz.openbmc_project.Common.FactoryReset", "Reset");
+ });
+}
/**
* ManagerResetActionInfo derived class for delivering Manager
* ResetType AllowableValues using ResetInfo schema.
*/
-class ManagerResetActionInfo : public Node
+inline void requestRoutesManagerResetActionInfo(App& app)
{
- public:
- /*
- * Default Constructor
- */
- ManagerResetActionInfo(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/ResetActionInfo/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
/**
* Functions triggers appropriate requests on DBus
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue = {
- {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
- {"@odata.id", "/redfish/v1/Managers/bmc/ResetActionInfo"},
- {"Name", "Reset Action Info"},
- {"Id", "ResetActionInfo"},
- {"Parameters",
- {{{"Name", "ResetType"},
- {"Required", true},
- {"DataType", "String"},
- {"AllowableValues", {"GracefulRestart", "ForceRestart"}}}}}};
- }
-};
+
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/ResetActionInfo/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue = {
+ {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
+ {"@odata.id", "/redfish/v1/Managers/bmc/ResetActionInfo"},
+ {"Name", "Reset Action Info"},
+ {"Id", "ResetActionInfo"},
+ {"Parameters",
+ {{{"Name", "ResetType"},
+ {"Required", true},
+ {"DataType", "String"},
+ {"AllowableValues",
+ {"GracefulRestart", "ForceRestart"}}}}}};
+ });
+}
static constexpr const char* objectManagerIface =
"org.freedesktop.DBus.ObjectManager";
@@ -1746,561 +1724,557 @@
"LocationCode",
"LocationCode");
}
-
-class Manager : public Node
+// avoid name collision systems.hpp
+inline void
+ managerGetLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
{
- public:
- Manager(App& app) : Node(app, "/redfish/v1/Managers/bmc/")
- {
+ BMCWEB_LOG_DEBUG << "Getting Manager Last Reset Time";
- uuid = persistent_data::getConfig().systemUuid;
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Managers/bmc";
- asyncResp->res.jsonValue["@odata.type"] = "#Manager.v1_11_0.Manager";
- asyncResp->res.jsonValue["Id"] = "bmc";
- asyncResp->res.jsonValue["Name"] = "OpenBmc Manager";
- asyncResp->res.jsonValue["Description"] =
- "Baseboard Management Controller";
- asyncResp->res.jsonValue["PowerState"] = "On";
- asyncResp->res.jsonValue["Status"] = {{"State", "Enabled"},
- {"Health", "OK"}};
- asyncResp->res.jsonValue["ManagerType"] = "BMC";
- asyncResp->res.jsonValue["UUID"] = systemd_utils::getUuid();
- asyncResp->res.jsonValue["ServiceEntryPointUUID"] = uuid;
- asyncResp->res.jsonValue["Model"] = "OpenBmc"; // TODO(ed), get model
-
- asyncResp->res.jsonValue["LogServices"] = {
- {"@odata.id", "/redfish/v1/Managers/bmc/LogServices"}};
-
- asyncResp->res.jsonValue["NetworkProtocol"] = {
- {"@odata.id", "/redfish/v1/Managers/bmc/NetworkProtocol"}};
-
- asyncResp->res.jsonValue["EthernetInterfaces"] = {
- {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces"}};
-
-#ifdef BMCWEB_ENABLE_VM_NBDPROXY
- asyncResp->res.jsonValue["VirtualMedia"] = {
- {"@odata.id", "/redfish/v1/Managers/bmc/VirtualMedia"}};
-#endif // BMCWEB_ENABLE_VM_NBDPROXY
-
- // default oem data
- nlohmann::json& oem = asyncResp->res.jsonValue["Oem"];
- nlohmann::json& oemOpenbmc = oem["OpenBmc"];
- oem["@odata.type"] = "#OemManager.Oem";
- oem["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem";
- oemOpenbmc["@odata.type"] = "#OemManager.OpenBmc";
- oemOpenbmc["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem/OpenBmc";
- oemOpenbmc["Certificates"] = {
- {"@odata.id", "/redfish/v1/Managers/bmc/Truststore/Certificates"}};
-
- // Manager.Reset (an action) can be many values, OpenBMC only supports
- // BMC reboot.
- nlohmann::json& managerReset =
- asyncResp->res.jsonValue["Actions"]["#Manager.Reset"];
- managerReset["target"] =
- "/redfish/v1/Managers/bmc/Actions/Manager.Reset";
- managerReset["@Redfish.ActionInfo"] =
- "/redfish/v1/Managers/bmc/ResetActionInfo";
-
- // ResetToDefaults (Factory Reset) has values like
- // PreserveNetworkAndUsers and PreserveNetwork that aren't supported
- // on OpenBMC
- nlohmann::json& resetToDefaults =
- asyncResp->res.jsonValue["Actions"]["#Manager.ResetToDefaults"];
- resetToDefaults["target"] =
- "/redfish/v1/Managers/bmc/Actions/Manager.ResetToDefaults";
- resetToDefaults["ResetType@Redfish.AllowableValues"] = {"ResetAll"};
-
- asyncResp->res.jsonValue["DateTime"] = crow::utility::dateTimeNow();
-
- // Fill in SerialConsole info
- asyncResp->res.jsonValue["SerialConsole"]["ServiceEnabled"] = true;
- asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
- asyncResp->res.jsonValue["SerialConsole"]["ConnectTypesSupported"] = {
- "IPMI", "SSH"};
-#ifdef BMCWEB_ENABLE_KVM
- // Fill in GraphicalConsole info
- asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
- asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
- 4;
- asyncResp->res
- .jsonValue["GraphicalConsole"]["ConnectTypesSupported"] = {"KVMIP"};
-#endif // BMCWEB_ENABLE_KVM
-
- asyncResp->res.jsonValue["Links"]["ManagerForServers@odata.count"] = 1;
- asyncResp->res.jsonValue["Links"]["ManagerForServers"] = {
- {{"@odata.id", "/redfish/v1/Systems/system"}}};
-
- auto health = std::make_shared<HealthPopulate>(asyncResp);
- health->isManagersHealth = true;
- health->populate();
-
- fw_util::populateFirmwareInformation(asyncResp, fw_util::bmcPurpose,
- "FirmwareVersion", true);
-
- getLastResetTime(asyncResp);
-
- auto pids = std::make_shared<GetPIDValues>(asyncResp);
- pids->run();
-
- getMainChassisId(
- asyncResp, [](const std::string& chassisId,
- const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
- aRsp->res.jsonValue["Links"]["ManagerForChassis@odata.count"] =
- 1;
- aRsp->res.jsonValue["Links"]["ManagerForChassis"] = {
- {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
- aRsp->res.jsonValue["Links"]["ManagerInChassis"] = {
- {"@odata.id", "/redfish/v1/Chassis/" + chassisId}};
- });
-
- static bool started = false;
-
- if (!started)
- {
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
- const std::variant<double>& resp) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "Error while getting progress";
- messages::internalError(asyncResp->res);
- return;
- }
- const double* val = std::get_if<double>(&resp);
- if (val == nullptr)
- {
- BMCWEB_LOG_ERROR
- << "Invalid response while getting progress";
- messages::internalError(asyncResp->res);
- return;
- }
- if (*val < 1.0)
- {
- asyncResp->res.jsonValue["Status"]["State"] =
- "Starting";
- started = true;
- }
- },
- "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
- "org.freedesktop.DBus.Properties", "Get",
- "org.freedesktop.systemd1.Manager", "Progress");
- }
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](
- const boost::system::error_code ec,
- const std::vector<std::pair<
- std::string, std::vector<std::pair<
- std::string, std::vector<std::string>>>>>&
- subtree) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree "
- << ec;
- return;
- }
- if (subtree.size() == 0)
- {
- BMCWEB_LOG_DEBUG << "Can't find bmc D-Bus object!";
- return;
- }
- // Assume only 1 bmc D-Bus object
- // Throw an error if there is more than 1
- if (subtree.size() > 1)
- {
- BMCWEB_LOG_DEBUG << "Found more than 1 bmc D-Bus object!";
- messages::internalError(asyncResp->res);
- return;
- }
-
- if (subtree[0].first.empty() || subtree[0].second.size() != 1)
- {
- BMCWEB_LOG_DEBUG << "Error getting bmc D-Bus object!";
- messages::internalError(asyncResp->res);
- return;
- }
-
- const std::string& path = subtree[0].first;
- const std::string& connectionName = subtree[0].second[0].first;
-
- for (const auto& interfaceName : subtree[0].second[0].second)
- {
- if (interfaceName ==
- "xyz.openbmc_project.Inventory.Decorator.Asset")
- {
- crow::connections::systemBus->async_method_call(
- [asyncResp](
- const boost::system::error_code ec,
- const std::vector<std::pair<
- std::string, std::variant<std::string>>>&
- propertiesList) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG << "Can't get bmc asset!";
- return;
- }
- for (const std::pair<std::string,
- std::variant<std::string>>&
- property : propertiesList)
- {
- const std::string& propertyName =
- property.first;
-
- if ((propertyName == "PartNumber") ||
- (propertyName == "SerialNumber") ||
- (propertyName == "Manufacturer") ||
- (propertyName == "Model") ||
- (propertyName == "SparePartNumber"))
- {
- const std::string* value =
- std::get_if<std::string>(
- &property.second);
- if (value == nullptr)
- {
- // illegal property
- messages::internalError(
- asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue[propertyName] =
- *value;
- }
- }
- },
- connectionName, path,
- "org.freedesktop.DBus.Properties", "GetAll",
- "xyz.openbmc_project.Inventory.Decorator.Asset");
- }
- else if (interfaceName == "xyz.openbmc_project.Inventory."
- "Decorator.LocationCode")
- {
- getLocation(asyncResp, connectionName, path);
- }
- }
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTree",
- "/xyz/openbmc_project/inventory", int32_t(0),
- std::array<const char*, 1>{
- "xyz.openbmc_project.Inventory.Item.Bmc"});
- }
-
- void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- std::optional<nlohmann::json> oem;
- std::optional<nlohmann::json> links;
- std::optional<std::string> datetime;
-
- if (!json_util::readJson(req, asyncResp->res, "Oem", oem, "DateTime",
- datetime, "Links", links))
- {
- return;
- }
-
- if (oem)
- {
- std::optional<nlohmann::json> openbmc;
- if (!redfish::json_util::readJson(*oem, asyncResp->res, "OpenBmc",
- openbmc))
+ crow::connections::systemBus->async_method_call(
+ [aResp](const boost::system::error_code ec,
+ std::variant<uint64_t>& lastResetTime) {
+ if (ec)
{
- BMCWEB_LOG_ERROR
- << "Illegal Property "
- << oem->dump(2, ' ', true,
- nlohmann::json::error_handler_t::replace);
+ BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
return;
}
- if (openbmc)
+
+ const uint64_t* lastResetTimePtr =
+ std::get_if<uint64_t>(&lastResetTime);
+
+ if (!lastResetTimePtr)
{
- std::optional<nlohmann::json> fan;
- if (!redfish::json_util::readJson(*openbmc, asyncResp->res,
- "Fan", fan))
- {
- BMCWEB_LOG_ERROR
- << "Illegal Property "
- << openbmc->dump(
- 2, ' ', true,
- nlohmann::json::error_handler_t::replace);
- return;
- }
- if (fan)
- {
- auto pid = std::make_shared<SetPIDValues>(asyncResp, *fan);
- pid->run();
- }
- }
- }
- if (links)
- {
- std::optional<nlohmann::json> activeSoftwareImage;
- if (!redfish::json_util::readJson(*links, asyncResp->res,
- "ActiveSoftwareImage",
- activeSoftwareImage))
- {
+ messages::internalError(aResp->res);
return;
}
- if (activeSoftwareImage)
+ // LastRebootTime is epoch time, in milliseconds
+ // https://github.com/openbmc/phosphor-dbus-interfaces/blob/7f9a128eb9296e926422ddc312c148b625890bb6/xyz/openbmc_project/State/BMC.interface.yaml#L19
+ time_t lastResetTimeStamp =
+ static_cast<time_t>(*lastResetTimePtr / 1000);
+
+ // Convert to ISO 8601 standard
+ aResp->res.jsonValue["LastResetTime"] =
+ crow::utility::getDateTime(lastResetTimeStamp);
+ },
+ "xyz.openbmc_project.State.BMC", "/xyz/openbmc_project/state/bmc0",
+ "org.freedesktop.DBus.Properties", "Get",
+ "xyz.openbmc_project.State.BMC", "LastRebootTime");
+}
+
+/**
+ * @brief Set the running firmware image
+ *
+ * @param[i,o] aResp - Async response object
+ * @param[i] runningFirmwareTarget - Image to make the running image
+ *
+ * @return void
+ */
+inline void
+ setActiveFirmwareImage(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+ const std::string& runningFirmwareTarget)
+{
+ // Get the Id from /redfish/v1/UpdateService/FirmwareInventory/<Id>
+ std::string::size_type idPos = runningFirmwareTarget.rfind('/');
+ if (idPos == std::string::npos)
+ {
+ messages::propertyValueNotInList(aResp->res, runningFirmwareTarget,
+ "@odata.id");
+ BMCWEB_LOG_DEBUG << "Can't parse firmware ID!";
+ return;
+ }
+ idPos++;
+ if (idPos >= runningFirmwareTarget.size())
+ {
+ messages::propertyValueNotInList(aResp->res, runningFirmwareTarget,
+ "@odata.id");
+ BMCWEB_LOG_DEBUG << "Invalid firmware ID.";
+ return;
+ }
+ std::string firmwareId = runningFirmwareTarget.substr(idPos);
+
+ // Make sure the image is valid before setting priority
+ crow::connections::systemBus->async_method_call(
+ [aResp, firmwareId, runningFirmwareTarget](
+ const boost::system::error_code ec, ManagedObjectType& subtree) {
+ if (ec)
{
- std::optional<std::string> odataId;
- if (!json_util::readJson(*activeSoftwareImage, asyncResp->res,
- "@odata.id", odataId))
+ BMCWEB_LOG_DEBUG << "D-Bus response error getting objects.";
+ messages::internalError(aResp->res);
+ return;
+ }
+
+ if (subtree.size() == 0)
+ {
+ BMCWEB_LOG_DEBUG << "Can't find image!";
+ messages::internalError(aResp->res);
+ return;
+ }
+
+ bool foundImage = false;
+ for (auto& object : subtree)
+ {
+ const std::string& path =
+ static_cast<const std::string&>(object.first);
+ std::size_t idPos2 = path.rfind('/');
+
+ if (idPos2 == std::string::npos)
{
- return;
+ continue;
}
- if (odataId)
+ idPos2++;
+ if (idPos2 >= path.size())
{
- setActiveFirmwareImage(asyncResp, *odataId);
+ continue;
+ }
+
+ if (path.substr(idPos2) == firmwareId)
+ {
+ foundImage = true;
+ break;
}
}
- }
- if (datetime)
- {
- setDateTime(asyncResp, std::move(*datetime));
- }
- }
- void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
- {
- BMCWEB_LOG_DEBUG << "Getting Manager Last Reset Time";
+ if (!foundImage)
+ {
+ messages::propertyValueNotInList(
+ aResp->res, runningFirmwareTarget, "@odata.id");
+ BMCWEB_LOG_DEBUG << "Invalid firmware ID.";
+ return;
+ }
- crow::connections::systemBus->async_method_call(
- [aResp](const boost::system::error_code ec,
- std::variant<uint64_t>& lastResetTime) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
- return;
- }
+ BMCWEB_LOG_DEBUG
+ << "Setting firmware version " + firmwareId + " to priority 0.";
- const uint64_t* lastResetTimePtr =
- std::get_if<uint64_t>(&lastResetTime);
-
- if (!lastResetTimePtr)
- {
- messages::internalError(aResp->res);
- return;
- }
- // LastRebootTime is epoch time, in milliseconds
- // https://github.com/openbmc/phosphor-dbus-interfaces/blob/7f9a128eb9296e926422ddc312c148b625890bb6/xyz/openbmc_project/State/BMC.interface.yaml#L19
- time_t lastResetTimeStamp =
- static_cast<time_t>(*lastResetTimePtr / 1000);
-
- // Convert to ISO 8601 standard
- aResp->res.jsonValue["LastResetTime"] =
- crow::utility::getDateTime(lastResetTimeStamp);
- },
- "xyz.openbmc_project.State.BMC", "/xyz/openbmc_project/state/bmc0",
- "org.freedesktop.DBus.Properties", "Get",
- "xyz.openbmc_project.State.BMC", "LastRebootTime");
- }
-
- /**
- * @brief Set the running firmware image
- *
- * @param[i,o] aResp - Async response object
- * @param[i] runningFirmwareTarget - Image to make the running image
- *
- * @return void
- */
- void setActiveFirmwareImage(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
- const std::string& runningFirmwareTarget)
- {
- // Get the Id from /redfish/v1/UpdateService/FirmwareInventory/<Id>
- std::string::size_type idPos = runningFirmwareTarget.rfind('/');
- if (idPos == std::string::npos)
- {
- messages::propertyValueNotInList(aResp->res, runningFirmwareTarget,
- "@odata.id");
- BMCWEB_LOG_DEBUG << "Can't parse firmware ID!";
- return;
- }
- idPos++;
- if (idPos >= runningFirmwareTarget.size())
- {
- messages::propertyValueNotInList(aResp->res, runningFirmwareTarget,
- "@odata.id");
- BMCWEB_LOG_DEBUG << "Invalid firmware ID.";
- return;
- }
- std::string firmwareId = runningFirmwareTarget.substr(idPos);
-
- // Make sure the image is valid before setting priority
- crow::connections::systemBus->async_method_call(
- [aResp, firmwareId,
- runningFirmwareTarget](const boost::system::error_code ec,
- ManagedObjectType& subtree) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG << "D-Bus response error getting objects.";
- messages::internalError(aResp->res);
- return;
- }
-
- if (subtree.size() == 0)
- {
- BMCWEB_LOG_DEBUG << "Can't find image!";
- messages::internalError(aResp->res);
- return;
- }
-
- bool foundImage = false;
- for (auto& object : subtree)
- {
- const std::string& path =
- static_cast<const std::string&>(object.first);
- std::size_t idPos2 = path.rfind('/');
-
- if (idPos2 == std::string::npos)
- {
- continue;
- }
-
- idPos2++;
- if (idPos2 >= path.size())
- {
- continue;
- }
-
- if (path.substr(idPos2) == firmwareId)
- {
- foundImage = true;
- break;
- }
- }
-
- if (!foundImage)
- {
- messages::propertyValueNotInList(
- aResp->res, runningFirmwareTarget, "@odata.id");
- BMCWEB_LOG_DEBUG << "Invalid firmware ID.";
- return;
- }
-
- BMCWEB_LOG_DEBUG << "Setting firmware version " + firmwareId +
- " to priority 0.";
-
- // Only support Immediate
- // An addition could be a Redfish Setting like
- // ActiveSoftwareImageApplyTime and support OnReset
- crow::connections::systemBus->async_method_call(
- [aResp](const boost::system::error_code ec) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG << "D-Bus response error setting.";
- messages::internalError(aResp->res);
- return;
- }
- doBMCGracefulRestart(aResp);
- },
-
- "xyz.openbmc_project.Software.BMC.Updater",
- "/xyz/openbmc_project/software/" + firmwareId,
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Software.RedundancyPriority",
- "Priority", std::variant<uint8_t>(static_cast<uint8_t>(0)));
- },
- "xyz.openbmc_project.Software.BMC.Updater",
- "/xyz/openbmc_project/software",
- "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
- }
-
- void setDateTime(std::shared_ptr<bmcweb::AsyncResp> aResp,
- std::string datetime) const
- {
- BMCWEB_LOG_DEBUG << "Set date time: " << datetime;
-
- std::stringstream stream(datetime);
- // Convert from ISO 8601 to boost local_time
- // (BMC only has time in UTC)
- boost::posix_time::ptime posixTime;
- boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
- // Facet gets deleted with the stringsteam
- auto ifc = std::make_unique<boost::local_time::local_time_input_facet>(
- "%Y-%m-%d %H:%M:%S%F %ZP");
- stream.imbue(std::locale(stream.getloc(), ifc.release()));
-
- boost::local_time::local_date_time ldt(
- boost::local_time::not_a_date_time);
-
- if (stream >> ldt)
- {
- posixTime = ldt.utc_time();
- boost::posix_time::time_duration dur = posixTime - epoch;
- uint64_t durMicroSecs =
- static_cast<uint64_t>(dur.total_microseconds());
+ // Only support Immediate
+ // An addition could be a Redfish Setting like
+ // ActiveSoftwareImageApplyTime and support OnReset
crow::connections::systemBus->async_method_call(
- [aResp{std::move(aResp)}, datetime{std::move(datetime)}](
- const boost::system::error_code ec) {
+ [aResp](const boost::system::error_code ec) {
if (ec)
{
- BMCWEB_LOG_DEBUG << "Failed to set elapsed time. "
- "DBUS response error "
- << ec;
+ BMCWEB_LOG_DEBUG << "D-Bus response error setting.";
messages::internalError(aResp->res);
return;
}
- aResp->res.jsonValue["DateTime"] = datetime;
+ doBMCGracefulRestart(aResp);
},
- "xyz.openbmc_project.Time.Manager",
- "/xyz/openbmc_project/time/bmc",
+
+ "xyz.openbmc_project.Software.BMC.Updater",
+ "/xyz/openbmc_project/software/" + firmwareId,
"org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Time.EpochTime", "Elapsed",
- std::variant<uint64_t>(durMicroSecs));
- }
- else
- {
- messages::propertyValueFormatError(aResp->res, datetime,
- "DateTime");
- return;
- }
- }
+ "xyz.openbmc_project.Software.RedundancyPriority", "Priority",
+ std::variant<uint8_t>(static_cast<uint8_t>(0)));
+ },
+ "xyz.openbmc_project.Software.BMC.Updater",
+ "/xyz/openbmc_project/software", "org.freedesktop.DBus.ObjectManager",
+ "GetManagedObjects");
+}
- std::string uuid;
-};
-
-class ManagerCollection : public Node
+inline void setDateTime(std::shared_ptr<bmcweb::AsyncResp> aResp,
+ std::string datetime)
{
- public:
- ManagerCollection(App& app) : Node(app, "/redfish/v1/Managers/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_LOG_DEBUG << "Set date time: " << datetime;
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
+ std::stringstream stream(datetime);
+ // Convert from ISO 8601 to boost local_time
+ // (BMC only has time in UTC)
+ boost::posix_time::ptime posixTime;
+ boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
+ // Facet gets deleted with the stringsteam
+ auto ifc = std::make_unique<boost::local_time::local_time_input_facet>(
+ "%Y-%m-%d %H:%M:%S%F %ZP");
+ stream.imbue(std::locale(stream.getloc(), ifc.release()));
+
+ boost::local_time::local_date_time ldt(boost::local_time::not_a_date_time);
+
+ if (stream >> ldt)
{
- // Collections don't include the static data added by SubRoute
- // because it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Managers";
- asyncResp->res.jsonValue["@odata.type"] =
- "#ManagerCollection.ManagerCollection";
- asyncResp->res.jsonValue["Name"] = "Manager Collection";
- asyncResp->res.jsonValue["Members@odata.count"] = 1;
- asyncResp->res.jsonValue["Members"] = {
- {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
+ posixTime = ldt.utc_time();
+ boost::posix_time::time_duration dur = posixTime - epoch;
+ uint64_t durMicroSecs = static_cast<uint64_t>(dur.total_microseconds());
+ crow::connections::systemBus->async_method_call(
+ [aResp{std::move(aResp)}, datetime{std::move(datetime)}](
+ const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "Failed to set elapsed time. "
+ "DBUS response error "
+ << ec;
+ messages::internalError(aResp->res);
+ return;
+ }
+ aResp->res.jsonValue["DateTime"] = datetime;
+ },
+ "xyz.openbmc_project.Time.Manager", "/xyz/openbmc_project/time/bmc",
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Time.EpochTime", "Elapsed",
+ std::variant<uint64_t>(durMicroSecs));
}
-};
+ else
+ {
+ messages::propertyValueFormatError(aResp->res, datetime, "DateTime");
+ return;
+ }
+}
+
+inline void requestRoutesManager(App& app)
+{
+ std::string uuid = persistent_data::getConfig().systemUuid;
+
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)([uuid](const crow::Request&,
+ const std::shared_ptr<
+ bmcweb::AsyncResp>&
+ asyncResp) {
+ asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Managers/bmc";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#Manager.v1_11_0.Manager";
+ asyncResp->res.jsonValue["Id"] = "bmc";
+ asyncResp->res.jsonValue["Name"] = "OpenBmc Manager";
+ asyncResp->res.jsonValue["Description"] =
+ "Baseboard Management Controller";
+ asyncResp->res.jsonValue["PowerState"] = "On";
+ asyncResp->res.jsonValue["Status"] = {{"State", "Enabled"},
+ {"Health", "OK"}};
+ asyncResp->res.jsonValue["ManagerType"] = "BMC";
+ asyncResp->res.jsonValue["UUID"] = systemd_utils::getUuid();
+ asyncResp->res.jsonValue["ServiceEntryPointUUID"] = uuid;
+ asyncResp->res.jsonValue["Model"] =
+ "OpenBmc"; // TODO(ed), get model
+
+ asyncResp->res.jsonValue["LogServices"] = {
+ {"@odata.id", "/redfish/v1/Managers/bmc/LogServices"}};
+
+ asyncResp->res.jsonValue["NetworkProtocol"] = {
+ {"@odata.id", "/redfish/v1/Managers/bmc/NetworkProtocol"}};
+
+ asyncResp->res.jsonValue["EthernetInterfaces"] = {
+ {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces"}};
+
+#ifdef BMCWEB_ENABLE_VM_NBDPROXY
+ asyncResp->res.jsonValue["VirtualMedia"] = {
+ {"@odata.id", "/redfish/v1/Managers/bmc/VirtualMedia"}};
+#endif // BMCWEB_ENABLE_VM_NBDPROXY
+
+ // default oem data
+ nlohmann::json& oem = asyncResp->res.jsonValue["Oem"];
+ nlohmann::json& oemOpenbmc = oem["OpenBmc"];
+ oem["@odata.type"] = "#OemManager.Oem";
+ oem["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem";
+ oemOpenbmc["@odata.type"] = "#OemManager.OpenBmc";
+ oemOpenbmc["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem/OpenBmc";
+ oemOpenbmc["Certificates"] = {
+ {"@odata.id",
+ "/redfish/v1/Managers/bmc/Truststore/Certificates"}};
+
+ // Manager.Reset (an action) can be many values, OpenBMC only
+ // supports BMC reboot.
+ nlohmann::json& managerReset =
+ asyncResp->res.jsonValue["Actions"]["#Manager.Reset"];
+ managerReset["target"] =
+ "/redfish/v1/Managers/bmc/Actions/Manager.Reset";
+ managerReset["@Redfish.ActionInfo"] =
+ "/redfish/v1/Managers/bmc/ResetActionInfo";
+
+ // ResetToDefaults (Factory Reset) has values like
+ // PreserveNetworkAndUsers and PreserveNetwork that aren't supported
+ // on OpenBMC
+ nlohmann::json& resetToDefaults =
+ asyncResp->res.jsonValue["Actions"]["#Manager.ResetToDefaults"];
+ resetToDefaults["target"] =
+ "/redfish/v1/Managers/bmc/Actions/Manager.ResetToDefaults";
+ resetToDefaults["ResetType@Redfish.AllowableValues"] = {"ResetAll"};
+
+ asyncResp->res.jsonValue["DateTime"] = crow::utility::dateTimeNow();
+
+ // Fill in SerialConsole info
+ asyncResp->res.jsonValue["SerialConsole"]["ServiceEnabled"] = true;
+ asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
+ 15;
+ asyncResp->res.jsonValue["SerialConsole"]["ConnectTypesSupported"] =
+ {"IPMI", "SSH"};
+#ifdef BMCWEB_ENABLE_KVM
+ // Fill in GraphicalConsole info
+ asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] =
+ true;
+ asyncResp->res
+ .jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] = 4;
+ asyncResp->res.jsonValue["GraphicalConsole"]
+ ["ConnectTypesSupported"] = {"KVMIP"};
+#endif // BMCWEB_ENABLE_KVM
+
+ asyncResp->res.jsonValue["Links"]["ManagerForServers@odata.count"] =
+ 1;
+ asyncResp->res.jsonValue["Links"]["ManagerForServers"] = {
+ {{"@odata.id", "/redfish/v1/Systems/system"}}};
+
+ auto health = std::make_shared<HealthPopulate>(asyncResp);
+ health->isManagersHealth = true;
+ health->populate();
+
+ fw_util::populateFirmwareInformation(asyncResp, fw_util::bmcPurpose,
+ "FirmwareVersion", true);
+
+ managerGetLastResetTime(asyncResp);
+
+ auto pids = std::make_shared<GetPIDValues>(asyncResp);
+ pids->run();
+
+ getMainChassisId(
+ asyncResp, [](const std::string& chassisId,
+ const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
+ aRsp->res
+ .jsonValue["Links"]["ManagerForChassis@odata.count"] =
+ 1;
+ aRsp->res.jsonValue["Links"]["ManagerForChassis"] = {
+ {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
+ aRsp->res.jsonValue["Links"]["ManagerInChassis"] = {
+ {"@odata.id", "/redfish/v1/Chassis/" + chassisId}};
+ });
+
+ static bool started = false;
+
+ if (!started)
+ {
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec,
+ const std::variant<double>& resp) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "Error while getting progress";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ const double* val = std::get_if<double>(&resp);
+ if (val == nullptr)
+ {
+ BMCWEB_LOG_ERROR
+ << "Invalid response while getting progress";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (*val < 1.0)
+ {
+ asyncResp->res.jsonValue["Status"]["State"] =
+ "Starting";
+ started = true;
+ }
+ },
+ "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
+ "org.freedesktop.DBus.Properties", "Get",
+ "org.freedesktop.systemd1.Manager", "Progress");
+ }
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](
+ const boost::system::error_code ec,
+ const std::vector<
+ std::pair<std::string,
+ std::vector<std::pair<
+ std::string, std::vector<std::string>>>>>&
+ subtree) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG
+ << "D-Bus response error on GetSubTree " << ec;
+ return;
+ }
+ if (subtree.size() == 0)
+ {
+ BMCWEB_LOG_DEBUG << "Can't find bmc D-Bus object!";
+ return;
+ }
+ // Assume only 1 bmc D-Bus object
+ // Throw an error if there is more than 1
+ if (subtree.size() > 1)
+ {
+ BMCWEB_LOG_DEBUG
+ << "Found more than 1 bmc D-Bus object!";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ if (subtree[0].first.empty() ||
+ subtree[0].second.size() != 1)
+ {
+ BMCWEB_LOG_DEBUG << "Error getting bmc D-Bus object!";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ const std::string& path = subtree[0].first;
+ const std::string& connectionName =
+ subtree[0].second[0].first;
+
+ for (const auto& interfaceName :
+ subtree[0].second[0].second)
+ {
+ if (interfaceName ==
+ "xyz.openbmc_project.Inventory.Decorator.Asset")
+ {
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](
+ const boost::system::error_code ec,
+ const std::vector<
+ std::pair<std::string,
+ std::variant<std::string>>>&
+ propertiesList) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG
+ << "Can't get bmc asset!";
+ return;
+ }
+ for (const std::pair<
+ std::string,
+ std::variant<std::string>>&
+ property : propertiesList)
+ {
+ const std::string& propertyName =
+ property.first;
+
+ if ((propertyName == "PartNumber") ||
+ (propertyName == "SerialNumber") ||
+ (propertyName == "Manufacturer") ||
+ (propertyName == "Model") ||
+ (propertyName == "SparePartNumber"))
+ {
+ const std::string* value =
+ std::get_if<std::string>(
+ &property.second);
+ if (value == nullptr)
+ {
+ // illegal property
+ messages::internalError(
+ asyncResp->res);
+ return;
+ }
+ asyncResp->res
+ .jsonValue[propertyName] =
+ *value;
+ }
+ }
+ },
+ connectionName, path,
+ "org.freedesktop.DBus.Properties", "GetAll",
+ "xyz.openbmc_project.Inventory.Decorator."
+ "Asset");
+ }
+ else if (interfaceName ==
+ "xyz.openbmc_project.Inventory."
+ "Decorator.LocationCode")
+ {
+ getLocation(asyncResp, connectionName, path);
+ }
+ }
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/inventory", int32_t(0),
+ std::array<const char*, 1>{
+ "xyz.openbmc_project.Inventory.Item.Bmc"});
+ });
+
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/")
+ .privileges({"ConfigureManager"})
+ .methods(
+ boost::beast::http::verb::
+ patch)([](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ std::optional<nlohmann::json> oem;
+ std::optional<nlohmann::json> links;
+ std::optional<std::string> datetime;
+
+ if (!json_util::readJson(req, asyncResp->res, "Oem", oem,
+ "DateTime", datetime, "Links", links))
+ {
+ return;
+ }
+
+ if (oem)
+ {
+ std::optional<nlohmann::json> openbmc;
+ if (!redfish::json_util::readJson(*oem, asyncResp->res,
+ "OpenBmc", openbmc))
+ {
+ BMCWEB_LOG_ERROR
+ << "Illegal Property "
+ << oem->dump(2, ' ', true,
+ nlohmann::json::error_handler_t::replace);
+ return;
+ }
+ if (openbmc)
+ {
+ std::optional<nlohmann::json> fan;
+ if (!redfish::json_util::readJson(*openbmc, asyncResp->res,
+ "Fan", fan))
+ {
+ BMCWEB_LOG_ERROR
+ << "Illegal Property "
+ << openbmc->dump(
+ 2, ' ', true,
+ nlohmann::json::error_handler_t::replace);
+ return;
+ }
+ if (fan)
+ {
+ auto pid =
+ std::make_shared<SetPIDValues>(asyncResp, *fan);
+ pid->run();
+ }
+ }
+ }
+ if (links)
+ {
+ std::optional<nlohmann::json> activeSoftwareImage;
+ if (!redfish::json_util::readJson(*links, asyncResp->res,
+ "ActiveSoftwareImage",
+ activeSoftwareImage))
+ {
+ return;
+ }
+ if (activeSoftwareImage)
+ {
+ std::optional<std::string> odataId;
+ if (!json_util::readJson(*activeSoftwareImage,
+ asyncResp->res, "@odata.id",
+ odataId))
+ {
+ return;
+ }
+
+ if (odataId)
+ {
+ setActiveFirmwareImage(asyncResp, *odataId);
+ }
+ }
+ }
+ if (datetime)
+ {
+ setDateTime(asyncResp, std::move(*datetime));
+ }
+ });
+}
+
+inline void requestRoutesManagerCollection(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Managers";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#ManagerCollection.ManagerCollection";
+ asyncResp->res.jsonValue["Name"] = "Manager Collection";
+ asyncResp->res.jsonValue["Members@odata.count"] = 1;
+ asyncResp->res.jsonValue["Members"] = {
+ {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/memory.hpp b/redfish-core/lib/memory.hpp
index 70886d2..465beae 100644
--- a/redfish-core/lib/memory.hpp
+++ b/redfish-core/lib/memory.hpp
@@ -17,9 +17,9 @@
#include "health.hpp"
+#include <app.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/format.hpp>
-#include <node.hpp>
#include <utils/collection.hpp>
#include <utils/json_utils.hpp>
@@ -880,83 +880,46 @@
"xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition"});
}
-class MemoryCollection : public Node
+inline void requestRoutesMemoryCollection(App& app)
{
- public:
- /*
- * Default Constructor
- */
- MemoryCollection(App& app) : Node(app, "/redfish/v1/Systems/system/Memory/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
/**
* Functions triggers appropriate requests on DBus
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.type"] =
- "#MemoryCollection.MemoryCollection";
- asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/Memory";
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#MemoryCollection.MemoryCollection";
+ asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/Memory";
- collection_util::getCollectionMembers(
- asyncResp, "/redfish/v1/Systems/system/Memory",
- {"xyz.openbmc_project.Inventory.Item.Dimm"});
- }
-};
+ collection_util::getCollectionMembers(
+ asyncResp, "/redfish/v1/Systems/system/Memory",
+ {"xyz.openbmc_project.Inventory.Item.Dimm"});
+ });
+}
-class Memory : public Node
+inline void requestRoutesMemory(App& app)
{
- public:
- /*
- * Default Constructor
- */
- Memory(App& app) :
- Node(app, "/redfish/v1/Systems/system/Memory/<str>/", std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
/**
* Functions triggers appropriate requests on DBus
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- // Check if there is required param, truly entering this shall be
- // impossible
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& dimmId = params[0];
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Memory/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& dimmId) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#Memory.v1_11_0.Memory";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/Memory/" + dimmId;
- asyncResp->res.jsonValue["@odata.type"] = "#Memory.v1_11_0.Memory";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/Memory/" + dimmId;
-
- getDimmData(asyncResp, dimmId);
- }
-};
+ getDimmData(asyncResp, dimmId);
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/message_registries.hpp b/redfish-core/lib/message_registries.hpp
index 455bf70..d0757b3 100644
--- a/redfish-core/lib/message_registries.hpp
+++ b/redfish-core/lib/message_registries.hpp
@@ -15,257 +15,215 @@
*/
#pragma once
-#include "node.hpp"
#include "registries.hpp"
#include "registries/base_message_registry.hpp"
#include "registries/openbmc_message_registry.hpp"
#include "registries/resource_event_message_registry.hpp"
#include "registries/task_event_message_registry.hpp"
+#include <app.hpp>
+
namespace redfish
{
-class MessageRegistryFileCollection : public Node
+inline void requestRoutesMessageRegistryFileCollection(App& app)
{
- public:
- MessageRegistryFileCollection(App& app) :
- Node(app, "/redfish/v1/Registries/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
/**
* Functions triggers appropriate requests on DBus
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- // Collections don't include the static data added by SubRoute because
- // it has a duplicate entry for members
+ BMCWEB_ROUTE(app, "/redfish/v1/Registries/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
- asyncResp->res.jsonValue = {
- {"@odata.type",
- "#MessageRegistryFileCollection.MessageRegistryFileCollection"},
- {"@odata.id", "/redfish/v1/Registries"},
- {"Name", "MessageRegistryFile Collection"},
- {"Description", "Collection of MessageRegistryFiles"},
- {"Members@odata.count", 4},
- {"Members",
- {{{"@odata.id", "/redfish/v1/Registries/Base"}},
- {{"@odata.id", "/redfish/v1/Registries/TaskEvent"}},
- {{"@odata.id", "/redfish/v1/Registries/ResourceEvent"}},
- {{"@odata.id", "/redfish/v1/Registries/OpenBMC"}}}}};
- }
-};
+ asyncResp->res.jsonValue = {
+ {"@odata.type", "#MessageRegistryFileCollection."
+ "MessageRegistryFileCollection"},
+ {"@odata.id", "/redfish/v1/Registries"},
+ {"Name", "MessageRegistryFile Collection"},
+ {"Description", "Collection of MessageRegistryFiles"},
+ {"Members@odata.count", 4},
+ {"Members",
+ {{{"@odata.id", "/redfish/v1/Registries/Base"}},
+ {{"@odata.id", "/redfish/v1/Registries/TaskEvent"}},
+ {{"@odata.id", "/redfish/v1/Registries/ResourceEvent"}},
+ {{"@odata.id", "/redfish/v1/Registries/OpenBMC"}}}}};
+ });
+}
-class MessageRegistryFile : public Node
+inline void requestRoutesMessageRegistryFile(App& app)
{
- public:
- MessageRegistryFile(App& app) :
- Node(app, "/redfish/v1/Registries/<str>/", std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Registries/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& registry) {
+ const message_registries::Header* header;
+ std::string dmtf = "DMTF ";
+ const char* url = nullptr;
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- const std::string& registry = params[0];
- const message_registries::Header* header;
- std::string dmtf = "DMTF ";
- const char* url = nullptr;
-
- if (registry == "Base")
- {
- header = &message_registries::base::header;
- url = message_registries::base::url;
- }
- else if (registry == "TaskEvent")
- {
- header = &message_registries::task_event::header;
- url = message_registries::task_event::url;
- }
- else if (registry == "OpenBMC")
- {
- header = &message_registries::openbmc::header;
- dmtf.clear();
- }
- else if (registry == "ResourceEvent")
- {
- header = &message_registries::resource_event::header;
- url = message_registries::resource_event::url;
- }
- else
- {
- messages::resourceNotFound(
- asyncResp->res,
- "#MessageRegistryFile.v1_1_0.MessageRegistryFile", registry);
- return;
- }
-
- asyncResp->res.jsonValue = {
- {"@odata.id", "/redfish/v1/Registries/" + registry},
- {"@odata.type", "#MessageRegistryFile.v1_1_0.MessageRegistryFile"},
- {"Name", registry + " Message Registry File"},
- {"Description",
- dmtf + registry + " Message Registry File Location"},
- {"Id", header->registryPrefix},
- {"Registry", header->id},
- {"Languages", {"en"}},
- {"Languages@odata.count", 1},
- {"Location",
- {{{"Language", "en"},
- {"Uri",
- "/redfish/v1/Registries/" + registry + "/" + registry}}}},
- {"Location@odata.count", 1}};
-
- if (url != nullptr)
- {
- asyncResp->res.jsonValue["Location"][0]["PublicationUri"] = url;
- }
- }
-};
-
-class MessageRegistry : public Node
-{
- public:
- MessageRegistry(App& app) :
- Node(app, "/redfish/v1/Registries/<str>/<str>/", std::string(),
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 2)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- const std::string& registry = params[0];
- const std::string& registry1 = params[1];
-
- const message_registries::Header* header;
- std::vector<const message_registries::MessageEntry*> registryEntries;
- if (registry == "Base")
- {
- header = &message_registries::base::header;
- for (const message_registries::MessageEntry& entry :
- message_registries::base::registry)
- {
- registryEntries.emplace_back(&entry);
- }
- }
- else if (registry == "TaskEvent")
- {
- header = &message_registries::task_event::header;
- for (const message_registries::MessageEntry& entry :
- message_registries::task_event::registry)
- {
- registryEntries.emplace_back(&entry);
- }
- }
- else if (registry == "OpenBMC")
- {
- header = &message_registries::openbmc::header;
- for (const message_registries::MessageEntry& entry :
- message_registries::openbmc::registry)
- {
- registryEntries.emplace_back(&entry);
- }
- }
- else if (registry == "ResourceEvent")
- {
- header = &message_registries::resource_event::header;
- for (const message_registries::MessageEntry& entry :
- message_registries::resource_event::registry)
- {
- registryEntries.emplace_back(&entry);
- }
- }
- else
- {
- messages::resourceNotFound(
- asyncResp->res,
- "#MessageRegistryFile.v1_1_0.MessageRegistryFile", registry);
- return;
- }
-
- if (registry != registry1)
- {
- messages::resourceNotFound(asyncResp->res, header->type, registry1);
- return;
- }
-
- asyncResp->res.jsonValue = {
- {"@Redfish.Copyright", header->copyright},
- {"@odata.type", header->type},
- {"Id", header->id},
- {"Name", header->name},
- {"Language", header->language},
- {"Description", header->description},
- {"RegistryPrefix", header->registryPrefix},
- {"RegistryVersion", header->registryVersion},
- {"OwningEntity", header->owningEntity}};
-
- nlohmann::json& messageObj = asyncResp->res.jsonValue["Messages"];
-
- // Go through the Message Registry and populate each Message
- for (const message_registries::MessageEntry* message : registryEntries)
- {
- nlohmann::json& obj = messageObj[message->first];
- obj = {{"Description", message->second.description},
- {"Message", message->second.message},
- {"Severity", message->second.severity},
- {"MessageSeverity", message->second.messageSeverity},
- {"NumberOfArgs", message->second.numberOfArgs},
- {"Resolution", message->second.resolution}};
- if (message->second.numberOfArgs > 0)
- {
- nlohmann::json& messageParamArray = obj["ParamTypes"];
- for (const char* str : message->second.paramTypes)
+ if (registry == "Base")
{
- if (str == nullptr)
- {
- break;
- }
- messageParamArray.push_back(str);
+ header = &message_registries::base::header;
+ url = message_registries::base::url;
}
- }
- }
- }
-};
+ else if (registry == "TaskEvent")
+ {
+ header = &message_registries::task_event::header;
+ url = message_registries::task_event::url;
+ }
+ else if (registry == "OpenBMC")
+ {
+ header = &message_registries::openbmc::header;
+ dmtf.clear();
+ }
+ else if (registry == "ResourceEvent")
+ {
+ header = &message_registries::resource_event::header;
+ url = message_registries::resource_event::url;
+ }
+ else
+ {
+ messages::resourceNotFound(
+ asyncResp->res,
+ "#MessageRegistryFile.v1_1_0.MessageRegistryFile",
+ registry);
+ return;
+ }
+
+ asyncResp->res.jsonValue = {
+ {"@odata.id", "/redfish/v1/Registries/" + registry},
+ {"@odata.type",
+ "#MessageRegistryFile.v1_1_0.MessageRegistryFile"},
+ {"Name", registry + " Message Registry File"},
+ {"Description",
+ dmtf + registry + " Message Registry File Location"},
+ {"Id", header->registryPrefix},
+ {"Registry", header->id},
+ {"Languages", {"en"}},
+ {"Languages@odata.count", 1},
+ {"Location",
+ {{{"Language", "en"},
+ {"Uri", "/redfish/v1/Registries/" + registry + "/" +
+ registry}}}},
+ {"Location@odata.count", 1}};
+
+ if (url != nullptr)
+ {
+ asyncResp->res.jsonValue["Location"][0]["PublicationUri"] =
+ url;
+ }
+ });
+}
+
+inline void requestRoutesMessageRegistry(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Registries/<str>/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& registry, const std::string& registry1)
+
+ {
+ const message_registries::Header* header;
+ std::vector<const message_registries::MessageEntry*>
+ registryEntries;
+ if (registry == "Base")
+ {
+ header = &message_registries::base::header;
+ for (const message_registries::MessageEntry& entry :
+ message_registries::base::registry)
+ {
+ registryEntries.emplace_back(&entry);
+ }
+ }
+ else if (registry == "TaskEvent")
+ {
+ header = &message_registries::task_event::header;
+ for (const message_registries::MessageEntry& entry :
+ message_registries::task_event::registry)
+ {
+ registryEntries.emplace_back(&entry);
+ }
+ }
+ else if (registry == "OpenBMC")
+ {
+ header = &message_registries::openbmc::header;
+ for (const message_registries::MessageEntry& entry :
+ message_registries::openbmc::registry)
+ {
+ registryEntries.emplace_back(&entry);
+ }
+ }
+ else if (registry == "ResourceEvent")
+ {
+ header = &message_registries::resource_event::header;
+ for (const message_registries::MessageEntry& entry :
+ message_registries::resource_event::registry)
+ {
+ registryEntries.emplace_back(&entry);
+ }
+ }
+ else
+ {
+ messages::resourceNotFound(
+ asyncResp->res,
+ "#MessageRegistryFile.v1_1_0.MessageRegistryFile",
+ registry);
+ return;
+ }
+
+ if (registry != registry1)
+ {
+ messages::resourceNotFound(asyncResp->res, header->type,
+ registry1);
+ return;
+ }
+
+ asyncResp->res.jsonValue = {
+ {"@Redfish.Copyright", header->copyright},
+ {"@odata.type", header->type},
+ {"Id", header->id},
+ {"Name", header->name},
+ {"Language", header->language},
+ {"Description", header->description},
+ {"RegistryPrefix", header->registryPrefix},
+ {"RegistryVersion", header->registryVersion},
+ {"OwningEntity", header->owningEntity}};
+
+ nlohmann::json& messageObj =
+ asyncResp->res.jsonValue["Messages"];
+
+ // Go through the Message Registry and populate each Message
+ for (const message_registries::MessageEntry* message :
+ registryEntries)
+ {
+ nlohmann::json& obj = messageObj[message->first];
+ obj = {{"Description", message->second.description},
+ {"Message", message->second.message},
+ {"Severity", message->second.severity},
+ {"MessageSeverity", message->second.messageSeverity},
+ {"NumberOfArgs", message->second.numberOfArgs},
+ {"Resolution", message->second.resolution}};
+ if (message->second.numberOfArgs > 0)
+ {
+ nlohmann::json& messageParamArray = obj["ParamTypes"];
+ for (const char* str : message->second.paramTypes)
+ {
+ if (str == nullptr)
+ {
+ break;
+ }
+ messageParamArray.push_back(str);
+ }
+ }
+ }
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp
index ad15a05..24e53f9 100644
--- a/redfish-core/lib/metric_report.hpp
+++ b/redfish-core/lib/metric_report.hpp
@@ -1,8 +1,9 @@
#pragma once
-#include "node.hpp"
#include "utils/telemetry_utils.hpp"
+#include <app.hpp>
+
namespace redfish
{
@@ -59,85 +60,43 @@
}
} // namespace telemetry
-class MetricReportCollection : public Node
+inline void requestRoutesMetricReportCollection(App& app)
{
- public:
- MetricReportCollection(App& app) :
- Node(app, "/redfish/v1/TelemetryService/MetricReports/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReports/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#MetricReportCollection.MetricReportCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/TelemetryService/MetricReports";
+ asyncResp->res.jsonValue["Name"] = "Metric Report Collection";
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.type"] =
- "#MetricReportCollection.MetricReportCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/TelemetryService/MetricReports";
- asyncResp->res.jsonValue["Name"] = "Metric Report Collection";
+ telemetry::getReportCollection(asyncResp,
+ telemetry::metricReportUri);
+ });
+}
- telemetry::getReportCollection(asyncResp, telemetry::metricReportUri);
- }
-};
-
-class MetricReport : public Node
+inline void requestRoutesMetricReport(App& app)
{
- public:
- MetricReport(App& app) :
- Node(app, "/redfish/v1/TelemetryService/MetricReports/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- const std::string& id = params[0];
- const std::string reportPath = telemetry::getDbusReportPath(id);
- crow::connections::systemBus->async_method_call(
- [asyncResp, id, reportPath](const boost::system::error_code& ec) {
- if (ec.value() == EBADR ||
- ec == boost::system::errc::host_unreachable)
- {
- messages::resourceNotFound(asyncResp->res, "MetricReport",
- id);
- return;
- }
- if (ec)
- {
- BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
-
+ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReports/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& id) {
+ const std::string reportPath = telemetry::getDbusReportPath(id);
crow::connections::systemBus->async_method_call(
- [asyncResp, id](
- const boost::system::error_code ec,
- const std::variant<telemetry::TimestampReadings>& ret) {
+ [asyncResp, id,
+ reportPath](const boost::system::error_code& ec) {
+ if (ec.value() == EBADR ||
+ ec == boost::system::errc::host_unreachable)
+ {
+ messages::resourceNotFound(asyncResp->res,
+ "MetricReport", id);
+ return;
+ }
if (ec)
{
BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
@@ -145,14 +104,27 @@
return;
}
- telemetry::fillReport(asyncResp, id, ret);
+ crow::connections::systemBus->async_method_call(
+ [asyncResp,
+ id](const boost::system::error_code ec,
+ const std::variant<
+ telemetry::TimestampReadings>& ret) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR
+ << "respHandler DBus error " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ telemetry::fillReport(asyncResp, id, ret);
+ },
+ telemetry::service, reportPath,
+ "org.freedesktop.DBus.Properties", "Get",
+ telemetry::reportInterface, "Readings");
},
- telemetry::service, reportPath,
- "org.freedesktop.DBus.Properties", "Get",
- telemetry::reportInterface, "Readings");
- },
- telemetry::service, reportPath, telemetry::reportInterface,
- "Update");
- }
-};
+ telemetry::service, reportPath, telemetry::reportInterface,
+ "Update");
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp
index a1231b1..6dce89f 100644
--- a/redfish-core/lib/metric_report_definition.hpp
+++ b/redfish-core/lib/metric_report_definition.hpp
@@ -1,10 +1,10 @@
#pragma once
-#include "node.hpp"
#include "sensors.hpp"
#include "utils/telemetry_utils.hpp"
#include "utils/time_utils.hpp"
+#include <app.hpp>
#include <boost/container/flat_map.hpp>
#include <tuple>
@@ -347,171 +347,140 @@
};
} // namespace telemetry
-class MetricReportDefinitionCollection : public Node
+inline void requestRoutesMetricReportDefinitionCollection(App& app)
{
- public:
- MetricReportDefinitionCollection(App& app) :
- Node(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#MetricReportDefinitionCollection."
+ "MetricReportDefinitionCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/TelemetryService/MetricReportDefinitions";
+ asyncResp->res.jsonValue["Name"] =
+ "Metric Definition Collection";
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.type"] =
- "#MetricReportDefinitionCollection."
- "MetricReportDefinitionCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/TelemetryService/MetricReportDefinitions";
- asyncResp->res.jsonValue["Name"] = "Metric Definition Collection";
+ telemetry::getReportCollection(
+ asyncResp, telemetry::metricReportDefinitionUri);
+ });
- telemetry::getReportCollection(asyncResp,
- telemetry::metricReportDefinitionUri);
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ telemetry::AddReportArgs args;
+ if (!telemetry::getUserParameters(asyncResp->res, req, args))
+ {
+ return;
+ }
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- telemetry::AddReportArgs args;
- if (!telemetry::getUserParameters(asyncResp->res, req, args))
- {
- return;
- }
+ boost::container::flat_set<std::pair<std::string, std::string>>
+ chassisSensors;
+ if (!telemetry::getChassisSensorNode(asyncResp, args.metrics,
+ chassisSensors))
+ {
+ return;
+ }
- boost::container::flat_set<std::pair<std::string, std::string>>
- chassisSensors;
- if (!telemetry::getChassisSensorNode(asyncResp, args.metrics,
- chassisSensors))
- {
- return;
- }
+ auto addReportReq = std::make_shared<telemetry::AddReport>(
+ std::move(args), asyncResp);
+ for (const auto& [chassis, sensorType] : chassisSensors)
+ {
+ retrieveUriToDbusMap(
+ chassis, sensorType,
+ [asyncResp, addReportReq](
+ const boost::beast::http::status status,
+ const boost::container::flat_map<
+ std::string, std::string>& uriToDbus) {
+ if (status != boost::beast::http::status::ok)
+ {
+ BMCWEB_LOG_ERROR
+ << "Failed to retrieve URI to dbus "
+ "sensors map with err "
+ << static_cast<unsigned>(status);
+ return;
+ }
+ addReportReq->insert(uriToDbus);
+ });
+ }
+ });
+}
- auto addReportReq =
- std::make_shared<telemetry::AddReport>(std::move(args), asyncResp);
- for (const auto& [chassis, sensorType] : chassisSensors)
- {
- retrieveUriToDbusMap(
- chassis, sensorType,
- [asyncResp, addReportReq](
- const boost::beast::http::status status,
- const boost::container::flat_map<std::string, std::string>&
- uriToDbus) {
- if (status != boost::beast::http::status::ok)
- {
- BMCWEB_LOG_ERROR << "Failed to retrieve URI to dbus "
- "sensors map with err "
- << static_cast<unsigned>(status);
- return;
- }
- addReportReq->insert(uriToDbus);
- });
- }
- }
-};
-
-class MetricReportDefinition : public Node
+inline void requestRoutesMetricReportDefinition(App& app)
{
- public:
- MetricReportDefinition(App& app) :
- Node(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& id) {
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, id](
+ const boost::system::error_code ec,
+ const std::vector<std::pair<
+ std::string,
+ std::variant<std::string, bool, uint64_t,
+ telemetry::ReadingParameters>>>& ret) {
+ if (ec.value() == EBADR ||
+ ec == boost::system::errc::host_unreachable)
+ {
+ messages::resourceNotFound(
+ asyncResp->res, "MetricReportDefinition", id);
+ return;
+ }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
+ telemetry::fillReportDefinition(asyncResp, id, ret);
+ },
+ telemetry::service, telemetry::getDbusReportPath(id),
+ "org.freedesktop.DBus.Properties", "GetAll",
+ telemetry::reportInterface);
+ });
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::delete_)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& id)
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ {
+ const std::string reportPath = telemetry::getDbusReportPath(id);
- const std::string& id = params[0];
- crow::connections::systemBus->async_method_call(
- [asyncResp,
- id](const boost::system::error_code ec,
- const std::vector<std::pair<
- std::string, std::variant<std::string, bool, uint64_t,
- telemetry::ReadingParameters>>>&
- ret) {
- if (ec.value() == EBADR ||
- ec == boost::system::errc::host_unreachable)
- {
- messages::resourceNotFound(asyncResp->res,
- "MetricReportDefinition", id);
- return;
- }
- if (ec)
- {
- BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, id](const boost::system::error_code ec) {
+ /*
+ * boost::system::errc and std::errc are missing value
+ * for EBADR error that is defined in Linux.
+ */
+ if (ec.value() == EBADR)
+ {
+ messages::resourceNotFound(
+ asyncResp->res, "MetricReportDefinition", id);
+ return;
+ }
- telemetry::fillReportDefinition(asyncResp, id, ret);
- },
- telemetry::service, telemetry::getDbusReportPath(id),
- "org.freedesktop.DBus.Properties", "GetAll",
- telemetry::reportInterface);
- }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
- void doDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- const std::string& id = params[0];
- const std::string reportPath = telemetry::getDbusReportPath(id);
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, id](const boost::system::error_code ec) {
- /*
- * boost::system::errc and std::errc are missing value for
- * EBADR error that is defined in Linux.
- */
- if (ec.value() == EBADR)
- {
- messages::resourceNotFound(asyncResp->res,
- "MetricReportDefinition", id);
- return;
- }
-
- if (ec)
- {
- BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
-
- asyncResp->res.result(boost::beast::http::status::no_content);
- },
- telemetry::service, reportPath, "xyz.openbmc_project.Object.Delete",
- "Delete");
- }
-};
+ asyncResp->res.result(
+ boost::beast::http::status::no_content);
+ },
+ telemetry::service, reportPath,
+ "xyz.openbmc_project.Object.Delete", "Delete");
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/network_protocol.hpp b/redfish-core/lib/network_protocol.hpp
index 491204e..46b5405 100644
--- a/redfish-core/lib/network_protocol.hpp
+++ b/redfish-core/lib/network_protocol.hpp
@@ -16,9 +16,9 @@
#pragma once
#include "error_messages.hpp"
-#include "node.hpp"
#include "openbmc_dbus_rest.hpp"
+#include <app.hpp>
#include <utils/json_utils.hpp>
#include <optional>
@@ -26,6 +26,9 @@
namespace redfish
{
+void getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp);
+std::string getHostName();
+
enum NetworkProtocolUnitStructFields
{
NET_PROTO_UNIT_NAME,
@@ -125,428 +128,406 @@
"org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
}
-class NetworkProtocol : public Node
+void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
- public:
- NetworkProtocol(App& app) :
- Node(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#ManagerNetworkProtocol.v1_5_0.ManagerNetworkProtocol";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Managers/bmc/NetworkProtocol";
+ asyncResp->res.jsonValue["Id"] = "NetworkProtocol";
+ asyncResp->res.jsonValue["Name"] = "Manager Network Protocol";
+ asyncResp->res.jsonValue["Description"] = "Manager Network Service";
+ asyncResp->res.jsonValue["Status"]["Health"] = "OK";
+ asyncResp->res.jsonValue["Status"]["HealthRollup"] = "OK";
+ asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+
+ // HTTP is Mandatory attribute as per OCP Baseline Profile - v1.0.0,
+ // but from security perspective it is not recommended to use.
+ // Hence using protocolEnabled as false to make it OCP and security-wise
+ // compliant
+ asyncResp->res.jsonValue["HTTP"]["Port"] = 0;
+ asyncResp->res.jsonValue["HTTP"]["ProtocolEnabled"] = false;
+
+ for (auto& protocol : protocolToDBus)
{
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
+ asyncResp->res.jsonValue[protocol.first]["Port"] =
+ nlohmann::detail::value_t::null;
+ asyncResp->res.jsonValue[protocol.first]["ProtocolEnabled"] = false;
}
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- getData(asyncResp);
- }
+ std::string hostName = getHostName();
- std::string getHostName() const
- {
- std::string hostName;
+ asyncResp->res.jsonValue["HostName"] = hostName;
- std::array<char, HOST_NAME_MAX> hostNameCStr;
- if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0)
- {
- hostName = hostNameCStr.data();
- }
- return hostName;
- }
+ getNTPProtocolEnabled(asyncResp);
- void getNTPProtocolEnabled(
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
- {
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code errorCode,
- const std::variant<std::string>& timeSyncMethod) {
- if (errorCode)
+ // TODO Get eth0 interface data, and call the below callback for JSON
+ // preparation
+ getEthernetIfaceData(
+ [hostName, asyncResp](const bool& success,
+ const std::vector<std::string>& ntpServers,
+ const std::vector<std::string>& domainNames) {
+ if (!success)
+ {
+ messages::resourceNotFound(asyncResp->res, "EthernetInterface",
+ "eth0");
+ return;
+ }
+ asyncResp->res.jsonValue["NTP"]["NTPServers"] = ntpServers;
+ if (hostName.empty() == false)
+ {
+ std::string fqdn = hostName;
+ if (domainNames.empty() == false)
{
- return;
+ fqdn += ".";
+ fqdn += domainNames[0];
+ }
+ asyncResp->res.jsonValue["FQDN"] = std::move(fqdn);
+ }
+ });
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code e,
+ const std::vector<UnitStruct>& r) {
+ if (e)
+ {
+ asyncResp->res.jsonValue = nlohmann::json::object();
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["HTTPS"]["Certificates"] = {
+ {"@odata.id", "/redfish/v1/Managers/bmc/NetworkProtocol/"
+ "HTTPS/Certificates"}};
+
+ for (auto& unit : r)
+ {
+ /* Only traverse through <xyz>.socket units */
+ const std::string& unitName =
+ std::get<NET_PROTO_UNIT_NAME>(unit);
+ if (!boost::ends_with(unitName, ".socket"))
+ {
+ continue;
}
- const std::string* s =
- std::get_if<std::string>(&timeSyncMethod);
-
- if (*s == "xyz.openbmc_project.Time.Synchronization.Method.NTP")
+ for (auto& kv : protocolToDBus)
{
- asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = true;
- }
- else if (*s == "xyz.openbmc_project.Time.Synchronization."
- "Method.Manual")
- {
- asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = false;
- }
- },
- "xyz.openbmc_project.Settings",
- "/xyz/openbmc_project/time/sync_method",
- "org.freedesktop.DBus.Properties", "Get",
- "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod");
- }
-
- void getData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
- {
- asyncResp->res.jsonValue["@odata.type"] =
- "#ManagerNetworkProtocol.v1_5_0.ManagerNetworkProtocol";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Managers/bmc/NetworkProtocol";
- asyncResp->res.jsonValue["Id"] = "NetworkProtocol";
- asyncResp->res.jsonValue["Name"] = "Manager Network Protocol";
- asyncResp->res.jsonValue["Description"] = "Manager Network Service";
- asyncResp->res.jsonValue["Status"]["Health"] = "OK";
- asyncResp->res.jsonValue["Status"]["HealthRollup"] = "OK";
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
-
- // HTTP is Mandatory attribute as per OCP Baseline Profile - v1.0.0,
- // but from security perspective it is not recommended to use.
- // Hence using protocolEnabled as false to make it OCP and security-wise
- // compliant
- asyncResp->res.jsonValue["HTTP"]["Port"] = 0;
- asyncResp->res.jsonValue["HTTP"]["ProtocolEnabled"] = false;
-
- for (auto& protocol : protocolToDBus)
- {
- asyncResp->res.jsonValue[protocol.first]["Port"] =
- nlohmann::detail::value_t::null;
- asyncResp->res.jsonValue[protocol.first]["ProtocolEnabled"] = false;
- }
-
- std::string hostName = getHostName();
-
- asyncResp->res.jsonValue["HostName"] = hostName;
-
- getNTPProtocolEnabled(asyncResp);
-
- // TODO Get eth0 interface data, and call the below callback for JSON
- // preparation
- getEthernetIfaceData(
- [hostName, asyncResp](const bool& success,
- const std::vector<std::string>& ntpServers,
- const std::vector<std::string>& domainNames) {
- if (!success)
- {
- messages::resourceNotFound(asyncResp->res,
- "EthernetInterface", "eth0");
- return;
- }
- asyncResp->res.jsonValue["NTP"]["NTPServers"] = ntpServers;
- if (hostName.empty() == false)
- {
- std::string fqdn = hostName;
- if (domainNames.empty() == false)
- {
- fqdn += ".";
- fqdn += domainNames[0];
- }
- asyncResp->res.jsonValue["FQDN"] = std::move(fqdn);
- }
- });
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code e,
- const std::vector<UnitStruct>& r) {
- if (e)
- {
- asyncResp->res.jsonValue = nlohmann::json::object();
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue["HTTPS"]["Certificates"] = {
- {"@odata.id", "/redfish/v1/Managers/bmc/NetworkProtocol/"
- "HTTPS/Certificates"}};
-
- for (auto& unit : r)
- {
- /* Only traverse through <xyz>.socket units */
- const std::string& unitName =
- std::get<NET_PROTO_UNIT_NAME>(unit);
- if (!boost::ends_with(unitName, ".socket"))
+ // We are interested in services, which starts with
+ // mapped service name
+ if (!boost::starts_with(unitName, kv.second))
{
continue;
}
+ const char* rfServiceKey = kv.first;
+ const std::string& socketPath =
+ std::get<NET_PROTO_UNIT_OBJ_PATH>(unit);
+ const std::string& unitState =
+ std::get<NET_PROTO_UNIT_SUB_STATE>(unit);
- for (auto& kv : protocolToDBus)
- {
- // We are interested in services, which starts with
- // mapped service name
- if (!boost::starts_with(unitName, kv.second))
- {
- continue;
- }
- const char* rfServiceKey = kv.first;
- const std::string& socketPath =
- std::get<NET_PROTO_UNIT_OBJ_PATH>(unit);
- const std::string& unitState =
- std::get<NET_PROTO_UNIT_SUB_STATE>(unit);
+ asyncResp->res.jsonValue[rfServiceKey]["ProtocolEnabled"] =
+ (unitState == "running") || (unitState == "listening");
- asyncResp->res
- .jsonValue[rfServiceKey]["ProtocolEnabled"] =
- (unitState == "running") ||
- (unitState == "listening");
-
- crow::connections::systemBus->async_method_call(
- [asyncResp,
- rfServiceKey{std::string(rfServiceKey)}](
- const boost::system::error_code ec,
- const std::variant<std::vector<std::tuple<
- std::string, std::string>>>& resp) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::vector<
- std::tuple<std::string, std::string>>*
- responsePtr = std::get_if<std::vector<
- std::tuple<std::string, std::string>>>(
- &resp);
- if (responsePtr == nullptr ||
- responsePtr->size() < 1)
- {
- return;
- }
-
- const std::string& listenStream =
- std::get<NET_PROTO_LISTEN_STREAM>(
- (*responsePtr)[0]);
- std::size_t lastColonPos =
- listenStream.rfind(':');
- if (lastColonPos == std::string::npos)
- {
- // Not a port
- return;
- }
- std::string portStr =
- listenStream.substr(lastColonPos + 1);
- if (portStr.empty())
- {
- return;
- }
- char* endPtr = nullptr;
- errno = 0;
- // Use strtol instead of stroi to avoid
- // exceptions
- long port =
- std::strtol(portStr.c_str(), &endPtr, 10);
- if ((errno == 0) && (*endPtr == '\0'))
- {
- asyncResp->res
- .jsonValue[rfServiceKey]["Port"] = port;
- }
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, rfServiceKey{std::string(rfServiceKey)}](
+ const boost::system::error_code ec,
+ const std::variant<std::vector<
+ std::tuple<std::string, std::string>>>& resp) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
return;
- },
- "org.freedesktop.systemd1", socketPath,
- "org.freedesktop.DBus.Properties", "Get",
- "org.freedesktop.systemd1.Socket", "Listen");
+ }
+ const std::vector<
+ std::tuple<std::string, std::string>>*
+ responsePtr = std::get_if<std::vector<
+ std::tuple<std::string, std::string>>>(
+ &resp);
+ if (responsePtr == nullptr ||
+ responsePtr->size() < 1)
+ {
+ return;
+ }
- // We found service, break the inner loop.
- break;
- }
+ const std::string& listenStream =
+ std::get<NET_PROTO_LISTEN_STREAM>(
+ (*responsePtr)[0]);
+ std::size_t lastColonPos = listenStream.rfind(':');
+ if (lastColonPos == std::string::npos)
+ {
+ // Not a port
+ return;
+ }
+ std::string portStr =
+ listenStream.substr(lastColonPos + 1);
+ if (portStr.empty())
+ {
+ return;
+ }
+ char* endPtr = nullptr;
+ errno = 0;
+ // Use strtol instead of stroi to avoid
+ // exceptions
+ long port =
+ std::strtol(portStr.c_str(), &endPtr, 10);
+ if ((errno == 0) && (*endPtr == '\0'))
+ {
+ asyncResp->res.jsonValue[rfServiceKey]["Port"] =
+ port;
+ }
+ return;
+ },
+ "org.freedesktop.systemd1", socketPath,
+ "org.freedesktop.DBus.Properties", "Get",
+ "org.freedesktop.systemd1.Socket", "Listen");
+
+ // We found service, break the inner loop.
+ break;
}
- },
- "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager", "ListUnits");
- }
+ }
+ },
+ "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager", "ListUnits");
+}
#ifdef BMCWEB_ALLOW_DEPRECATED_HOSTNAME_PATCH
- void
- handleHostnamePatch(const std::string& hostName,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
- {
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- },
- "xyz.openbmc_project.Network",
- "/xyz/openbmc_project/network/config",
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
- std::variant<std::string>(hostName));
- }
+void handleHostnamePatch(const std::string& hostName,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
+ "xyz.openbmc_project.Network", "/xyz/openbmc_project/network/config",
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
+ std::variant<std::string>(hostName));
+}
#endif
- void handleNTPProtocolEnabled(
- const bool& ntpEnabled,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+void handleNTPProtocolEnabled(
+ const bool& ntpEnabled, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ std::string timeSyncMethod;
+ if (ntpEnabled)
{
- std::string timeSyncMethod;
- if (ntpEnabled)
- {
- timeSyncMethod =
- "xyz.openbmc_project.Time.Synchronization.Method.NTP";
- }
- else
- {
- timeSyncMethod =
- "xyz.openbmc_project.Time.Synchronization.Method.Manual";
- }
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code errorCode) {
- if (errorCode)
- {
- messages::internalError(asyncResp->res);
- }
- },
- "xyz.openbmc_project.Settings",
- "/xyz/openbmc_project/time/sync_method",
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod",
- std::variant<std::string>{timeSyncMethod});
+ timeSyncMethod = "xyz.openbmc_project.Time.Synchronization.Method.NTP";
+ }
+ else
+ {
+ timeSyncMethod =
+ "xyz.openbmc_project.Time.Synchronization.Method.Manual";
}
- void handleNTPServersPatch(
- const std::vector<std::string>& ntpServers,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
- {
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- },
- "xyz.openbmc_project.Network", "/xyz/openbmc_project/network/eth0",
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Network.EthernetInterface", "NTPServers",
- std::variant<std::vector<std::string>>{ntpServers});
- }
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code errorCode) {
+ if (errorCode)
+ {
+ messages::internalError(asyncResp->res);
+ }
+ },
+ "xyz.openbmc_project.Settings", "/xyz/openbmc_project/time/sync_method",
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod",
+ std::variant<std::string>{timeSyncMethod});
+}
- void handleIpmiProtocolEnabled(
- const bool ipmiProtocolEnabled,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
- {
- crow::connections::systemBus->async_method_call(
- [ipmiProtocolEnabled,
- asyncResp](const boost::system::error_code ec,
- const crow::openbmc_mapper::GetSubTreeType& subtree) {
- if (ec)
+void handleNTPServersPatch(const std::vector<std::string>& ntpServers,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
+ "xyz.openbmc_project.Network", "/xyz/openbmc_project/network/eth0",
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Network.EthernetInterface", "NTPServers",
+ std::variant<std::vector<std::string>>{ntpServers});
+}
+
+void handleIpmiProtocolEnabled(
+ const bool ipmiProtocolEnabled,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ crow::connections::systemBus->async_method_call(
+ [ipmiProtocolEnabled,
+ asyncResp](const boost::system::error_code ec,
+ const crow::openbmc_mapper::GetSubTreeType& subtree) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ constexpr char const* netipmidBasePath =
+ "/xyz/openbmc_project/control/service/"
+ "phosphor_2dipmi_2dnet_40";
+
+ for (const auto& entry : subtree)
+ {
+ if (boost::algorithm::starts_with(entry.first,
+ netipmidBasePath))
{
- messages::internalError(asyncResp->res);
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec2) {
+ if (ec2)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
+ entry.second.begin()->first, entry.first,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Control.Service.Attributes",
+ "Running", std::variant<bool>{ipmiProtocolEnabled});
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec2) {
+ if (ec2)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
+ entry.second.begin()->first, entry.first,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Control.Service.Attributes",
+ "Enabled", std::variant<bool>{ipmiProtocolEnabled});
+ }
+ }
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/control/service", 0,
+ std::array<const char*, 1>{
+ "xyz.openbmc_project.Control.Service.Attributes"});
+}
+
+std::string getHostName()
+{
+ std::string hostName;
+
+ std::array<char, HOST_NAME_MAX> hostNameCStr;
+ if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0)
+ {
+ hostName = hostNameCStr.data();
+ }
+ return hostName;
+}
+
+void getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code errorCode,
+ const std::variant<std::string>& timeSyncMethod) {
+ if (errorCode)
+ {
+ return;
+ }
+
+ const std::string* s = std::get_if<std::string>(&timeSyncMethod);
+
+ if (*s == "xyz.openbmc_project.Time.Synchronization.Method.NTP")
+ {
+ asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = true;
+ }
+ else if (*s == "xyz.openbmc_project.Time.Synchronization."
+ "Method.Manual")
+ {
+ asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = false;
+ }
+ },
+ "xyz.openbmc_project.Settings", "/xyz/openbmc_project/time/sync_method",
+ "org.freedesktop.DBus.Properties", "Get",
+ "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod");
+}
+
+inline void requestRoutesNetworkProtocol(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::patch)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ std::optional<std::string> newHostName;
+ std::optional<nlohmann::json> ntp;
+ std::optional<nlohmann::json> ipmi;
+
+ if (!json_util::readJson(req, asyncResp->res, "NTP", ntp,
+ "HostName", newHostName, "IPMI", ipmi))
+ {
return;
}
- constexpr char const* netipmidBasePath =
- "/xyz/openbmc_project/control/service/"
- "phosphor_2dipmi_2dnet_40";
-
- for (const auto& entry : subtree)
+ asyncResp->res.result(boost::beast::http::status::no_content);
+ if (newHostName)
{
- if (boost::algorithm::starts_with(entry.first,
- netipmidBasePath))
- {
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec2) {
- if (ec2)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- },
- entry.second.begin()->first, entry.first,
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Control.Service.Attributes",
- "Running", std::variant<bool>{ipmiProtocolEnabled});
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec2) {
- if (ec2)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- },
- entry.second.begin()->first, entry.first,
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Control.Service.Attributes",
- "Enabled", std::variant<bool>{ipmiProtocolEnabled});
- }
- }
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTree",
- "/xyz/openbmc_project/control/service", 0,
- std::array<const char*, 1>{
- "xyz.openbmc_project.Control.Service.Attributes"});
- }
-
- void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
-
- std::optional<std::string> newHostName;
- std::optional<nlohmann::json> ntp;
- std::optional<nlohmann::json> ipmi;
-
- if (!json_util::readJson(req, asyncResp->res, "NTP", ntp, "HostName",
- newHostName, "IPMI", ipmi))
- {
- return;
- }
-
- asyncResp->res.result(boost::beast::http::status::no_content);
- if (newHostName)
- {
#ifdef BMCWEB_ALLOW_DEPRECATED_HOSTNAME_PATCH
- handleHostnamePatch(*newHostName, asyncResp);
+ handleHostnamePatch(*newHostName, asyncResp);
#else
- messages::propertyNotWritable(asyncResp->res, "HostName");
+ messages::propertyNotWritable(asyncResp->res, "HostName");
#endif
- }
+ }
- if (ntp)
- {
- std::optional<std::vector<std::string>> ntpServers;
- std::optional<bool> ntpEnabled;
- if (!json_util::readJson(*ntp, asyncResp->res, "NTPServers",
- ntpServers, "ProtocolEnabled", ntpEnabled))
- {
- return;
- }
+ if (ntp)
+ {
+ std::optional<std::vector<std::string>> ntpServers;
+ std::optional<bool> ntpEnabled;
+ if (!json_util::readJson(*ntp, asyncResp->res, "NTPServers",
+ ntpServers, "ProtocolEnabled",
+ ntpEnabled))
+ {
+ return;
+ }
- if (ntpEnabled)
- {
- handleNTPProtocolEnabled(*ntpEnabled, asyncResp);
- }
+ if (ntpEnabled)
+ {
+ handleNTPProtocolEnabled(*ntpEnabled, asyncResp);
+ }
- if (ntpServers)
- {
- std::sort((*ntpServers).begin(), (*ntpServers).end());
- (*ntpServers)
- .erase(
- std::unique((*ntpServers).begin(), (*ntpServers).end()),
- (*ntpServers).end());
- handleNTPServersPatch(*ntpServers, asyncResp);
- }
- }
+ if (ntpServers)
+ {
+ std::sort((*ntpServers).begin(), (*ntpServers).end());
+ (*ntpServers)
+ .erase(std::unique((*ntpServers).begin(),
+ (*ntpServers).end()),
+ (*ntpServers).end());
+ handleNTPServersPatch(*ntpServers, asyncResp);
+ }
+ }
- if (ipmi)
- {
- std::optional<bool> ipmiProtocolEnabled;
- if (!json_util::readJson(*ipmi, asyncResp->res, "ProtocolEnabled",
- ipmiProtocolEnabled))
- {
- return;
- }
+ if (ipmi)
+ {
+ std::optional<bool> ipmiProtocolEnabled;
+ if (!json_util::readJson(*ipmi, asyncResp->res,
+ "ProtocolEnabled",
+ ipmiProtocolEnabled))
+ {
+ return;
+ }
- if (ipmiProtocolEnabled)
- {
- handleIpmiProtocolEnabled(*ipmiProtocolEnabled, asyncResp);
- }
- }
- }
-};
+ if (ipmiProtocolEnabled)
+ {
+ handleIpmiProtocolEnabled(*ipmiProtocolEnabled,
+ asyncResp);
+ }
+ }
+ });
+
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ getNetworkData(asyncResp);
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/pcie.hpp b/redfish-core/lib/pcie.hpp
index 35d20a5..15b2280 100644
--- a/redfish-core/lib/pcie.hpp
+++ b/redfish-core/lib/pcie.hpp
@@ -16,8 +16,7 @@
#pragma once
-#include "node.hpp"
-
+#include <app.hpp>
#include <boost/system/linux_error.hpp>
namespace redfish
@@ -70,73 +69,201 @@
std::string(pciePath) + "/", 1, std::array<std::string, 0>());
}
-class SystemPCIeDeviceCollection : public Node
+inline void requestRoutesSystemPCIeDeviceCollection(App& app)
{
- public:
- SystemPCIeDeviceCollection(App& app) :
- Node(app, "/redfish/v1/Systems/system/PCIeDevices/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
/**
* Functions triggers appropriate requests on DBus
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue = {
- {"@odata.type", "#PCIeDeviceCollection.PCIeDeviceCollection"},
- {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices"},
- {"Name", "PCIe Device Collection"},
- {"Description", "Collection of PCIe Devices"},
- {"Members", nlohmann::json::array()},
- {"Members@odata.count", 0}};
- getPCIeDeviceList(asyncResp, "Members");
- }
-};
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
-class SystemPCIeDevice : public Node
+ {
+ asyncResp->res.jsonValue = {
+ {"@odata.type",
+ "#PCIeDeviceCollection.PCIeDeviceCollection"},
+ {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices"},
+ {"Name", "PCIe Device Collection"},
+ {"Description", "Collection of PCIe Devices"},
+ {"Members", nlohmann::json::array()},
+ {"Members@odata.count", 0}};
+ getPCIeDeviceList(asyncResp, "Members");
+ });
+}
+
+inline void requestRoutesSystemPCIeDevice(App& app)
{
- public:
- SystemPCIeDevice(App& app) :
- Node(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& device)
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& device = params[0];
+ {
+ auto getPCIeDeviceCallback = [asyncResp, device](
+ const boost::system::error_code
+ ec,
+ boost::container::flat_map<
+ std::string,
+ std::variant<std::string>>&
+ pcieDevProperties) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG
+ << "failed to get PCIe Device properties ec: "
+ << ec.value() << ": " << ec.message();
+ if (ec.value() ==
+ boost::system::linux_error::bad_request_descriptor)
+ {
+ messages::resourceNotFound(asyncResp->res,
+ "PCIeDevice", device);
+ }
+ else
+ {
+ messages::internalError(asyncResp->res);
+ }
+ return;
+ }
- auto getPCIeDeviceCallback =
- [asyncResp,
- device](const boost::system::error_code ec,
- boost::container::flat_map<std::string,
- std::variant<std::string>>&
- pcieDevProperties) {
+ asyncResp->res.jsonValue = {
+ {"@odata.type", "#PCIeDevice.v1_4_0.PCIeDevice"},
+ {"@odata.id",
+ "/redfish/v1/Systems/system/PCIeDevices/" + device},
+ {"Name", "PCIe Device"},
+ {"Id", device}};
+
+ if (std::string* property = std::get_if<std::string>(
+ &pcieDevProperties["Manufacturer"]);
+ property)
+ {
+ asyncResp->res.jsonValue["Manufacturer"] = *property;
+ }
+
+ if (std::string* property = std::get_if<std::string>(
+ &pcieDevProperties["DeviceType"]);
+ property)
+ {
+ asyncResp->res.jsonValue["DeviceType"] = *property;
+ }
+
+ asyncResp->res.jsonValue["PCIeFunctions"] = {
+ {"@odata.id",
+ "/redfish/v1/Systems/system/PCIeDevices/" + device +
+ "/PCIeFunctions"}};
+ };
+ std::string escapedPath = std::string(pciePath) + "/" + device;
+ dbus::utility::escapePathForDbus(escapedPath);
+ crow::connections::systemBus->async_method_call(
+ std::move(getPCIeDeviceCallback), pcieService, escapedPath,
+ "org.freedesktop.DBus.Properties", "GetAll",
+ pcieDeviceInterface);
+ });
+}
+
+inline void requestRoutesSystemPCIeFunctionCollection(App& app)
+{
+ /**
+ * Functions triggers appropriate requests on DBus
+ */
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& device)
+
+ {
+ asyncResp->res.jsonValue = {
+ {"@odata.type",
+ "#PCIeFunctionCollection.PCIeFunctionCollection"},
+ {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" +
+ device + "/PCIeFunctions"},
+ {"Name", "PCIe Function Collection"},
+ {"Description",
+ "Collection of PCIe Functions for PCIe Device " + device}};
+
+ auto getPCIeDeviceCallback = [asyncResp, device](
+ const boost::system::error_code
+ ec,
+ boost::container::flat_map<
+ std::string,
+ std::variant<std::string>>&
+ pcieDevProperties) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG
+ << "failed to get PCIe Device properties ec: "
+ << ec.value() << ": " << ec.message();
+ if (ec.value() ==
+ boost::system::linux_error::bad_request_descriptor)
+ {
+ messages::resourceNotFound(asyncResp->res,
+ "PCIeDevice", device);
+ }
+ else
+ {
+ messages::internalError(asyncResp->res);
+ }
+ return;
+ }
+
+ nlohmann::json& pcieFunctionList =
+ asyncResp->res.jsonValue["Members"];
+ pcieFunctionList = nlohmann::json::array();
+ static constexpr const int maxPciFunctionNum = 8;
+ for (int functionNum = 0; functionNum < maxPciFunctionNum;
+ functionNum++)
+ {
+ // Check if this function exists by looking for a device
+ // ID
+ std::string devIDProperty =
+ "Function" + std::to_string(functionNum) +
+ "DeviceId";
+ std::string* property = std::get_if<std::string>(
+ &pcieDevProperties[devIDProperty]);
+ if (property && !property->empty())
+ {
+ pcieFunctionList.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Systems/system/PCIeDevices/" +
+ device + "/PCIeFunctions/" +
+ std::to_string(functionNum)}});
+ }
+ }
+ asyncResp->res.jsonValue["PCIeFunctions@odata.count"] =
+ pcieFunctionList.size();
+ };
+ std::string escapedPath = std::string(pciePath) + "/" + device;
+ dbus::utility::escapePathForDbus(escapedPath);
+ crow::connections::systemBus->async_method_call(
+ std::move(getPCIeDeviceCallback), pcieService, escapedPath,
+ "org.freedesktop.DBus.Properties", "GetAll",
+ pcieDeviceInterface);
+ });
+}
+
+inline void requestRoutesSystemPCIeFunction(App& app)
+{
+ BMCWEB_ROUTE(
+ app,
+ "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::get)([](const crow::Request&,
+ const std::shared_ptr<
+ bmcweb::AsyncResp>& asyncResp,
+ const std::string& device,
+ const std::string& function) {
+ auto getPCIeDeviceCallback = [asyncResp, device, function](
+ const boost::system::error_code ec,
+ boost::container::flat_map<
+ std::string,
+ std::variant<std::string>>&
+ pcieDevProperties) {
if (ec)
{
BMCWEB_LOG_DEBUG
@@ -155,274 +282,99 @@
return;
}
+ // Check if this function exists by looking for a device ID
+ std::string devIDProperty = "Function" + function + "DeviceId";
+ if (std::string* property = std::get_if<std::string>(
+ &pcieDevProperties[devIDProperty]);
+ property && property->empty())
+ {
+ messages::resourceNotFound(asyncResp->res, "PCIeFunction",
+ function);
+ return;
+ }
+
asyncResp->res.jsonValue = {
- {"@odata.type", "#PCIeDevice.v1_4_0.PCIeDevice"},
- {"@odata.id",
- "/redfish/v1/Systems/system/PCIeDevices/" + device},
- {"Name", "PCIe Device"},
- {"Id", device}};
-
- if (std::string* property = std::get_if<std::string>(
- &pcieDevProperties["Manufacturer"]);
- property)
- {
- asyncResp->res.jsonValue["Manufacturer"] = *property;
- }
-
- if (std::string* property = std::get_if<std::string>(
- &pcieDevProperties["DeviceType"]);
- property)
- {
- asyncResp->res.jsonValue["DeviceType"] = *property;
- }
-
- asyncResp->res.jsonValue["PCIeFunctions"] = {
+ {"@odata.type", "#PCIeFunction.v1_2_0.PCIeFunction"},
{"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" +
- device + "/PCIeFunctions"}};
+ device + "/PCIeFunctions/" + function},
+ {"Name", "PCIe Function"},
+ {"Id", function},
+ {"FunctionId", std::stoi(function)},
+ {"Links",
+ {{"PCIeDevice",
+ {{"@odata.id",
+ "/redfish/v1/Systems/system/PCIeDevices/" +
+ device}}}}}};
+
+ if (std::string* property = std::get_if<std::string>(
+ &pcieDevProperties["Function" + function + "DeviceId"]);
+ property)
+ {
+ asyncResp->res.jsonValue["DeviceId"] = *property;
+ }
+
+ if (std::string* property = std::get_if<std::string>(
+ &pcieDevProperties["Function" + function + "VendorId"]);
+ property)
+ {
+ asyncResp->res.jsonValue["VendorId"] = *property;
+ }
+
+ if (std::string* property = std::get_if<std::string>(
+ &pcieDevProperties["Function" + function +
+ "FunctionType"]);
+ property)
+ {
+ asyncResp->res.jsonValue["FunctionType"] = *property;
+ }
+
+ if (std::string* property = std::get_if<std::string>(
+ &pcieDevProperties["Function" + function +
+ "DeviceClass"]);
+ property)
+ {
+ asyncResp->res.jsonValue["DeviceClass"] = *property;
+ }
+
+ if (std::string* property = std::get_if<std::string>(
+ &pcieDevProperties["Function" + function +
+ "ClassCode"]);
+ property)
+ {
+ asyncResp->res.jsonValue["ClassCode"] = *property;
+ }
+
+ if (std::string* property = std::get_if<std::string>(
+ &pcieDevProperties["Function" + function +
+ "RevisionId"]);
+ property)
+ {
+ asyncResp->res.jsonValue["RevisionId"] = *property;
+ }
+
+ if (std::string* property = std::get_if<std::string>(
+ &pcieDevProperties["Function" + function +
+ "SubsystemId"]);
+ property)
+ {
+ asyncResp->res.jsonValue["SubsystemId"] = *property;
+ }
+
+ if (std::string* property = std::get_if<std::string>(
+ &pcieDevProperties["Function" + function +
+ "SubsystemVendorId"]);
+ property)
+ {
+ asyncResp->res.jsonValue["SubsystemVendorId"] = *property;
+ }
};
- std::string escapedPath = std::string(pciePath) + "/" + device;
- dbus::utility::escapePathForDbus(escapedPath);
- crow::connections::systemBus->async_method_call(
- std::move(getPCIeDeviceCallback), pcieService, escapedPath,
- "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
- }
-};
-
-class SystemPCIeFunctionCollection : public Node
-{
- public:
- SystemPCIeFunctionCollection(App& app) :
- Node(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& device = params[0];
- asyncResp->res.jsonValue = {
- {"@odata.type", "#PCIeFunctionCollection.PCIeFunctionCollection"},
- {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" + device +
- "/PCIeFunctions"},
- {"Name", "PCIe Function Collection"},
- {"Description",
- "Collection of PCIe Functions for PCIe Device " + device}};
-
- auto getPCIeDeviceCallback =
- [asyncResp,
- device](const boost::system::error_code ec,
- boost::container::flat_map<std::string,
- std::variant<std::string>>&
- pcieDevProperties) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG
- << "failed to get PCIe Device properties ec: "
- << ec.value() << ": " << ec.message();
- if (ec.value() ==
- boost::system::linux_error::bad_request_descriptor)
- {
- messages::resourceNotFound(asyncResp->res, "PCIeDevice",
- device);
- }
- else
- {
- messages::internalError(asyncResp->res);
- }
- return;
- }
-
- nlohmann::json& pcieFunctionList =
- asyncResp->res.jsonValue["Members"];
- pcieFunctionList = nlohmann::json::array();
- static constexpr const int maxPciFunctionNum = 8;
- for (int functionNum = 0; functionNum < maxPciFunctionNum;
- functionNum++)
- {
- // Check if this function exists by looking for a device ID
- std::string devIDProperty =
- "Function" + std::to_string(functionNum) + "DeviceId";
- std::string* property = std::get_if<std::string>(
- &pcieDevProperties[devIDProperty]);
- if (property && !property->empty())
- {
- pcieFunctionList.push_back(
- {{"@odata.id",
- "/redfish/v1/Systems/system/PCIeDevices/" +
- device + "/PCIeFunctions/" +
- std::to_string(functionNum)}});
- }
- }
- asyncResp->res.jsonValue["PCIeFunctions@odata.count"] =
- pcieFunctionList.size();
- };
- std::string escapedPath = std::string(pciePath) + "/" + device;
- dbus::utility::escapePathForDbus(escapedPath);
- crow::connections::systemBus->async_method_call(
- std::move(getPCIeDeviceCallback), pcieService, escapedPath,
- "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
- }
-};
-
-class SystemPCIeFunction : public Node
-{
- public:
- SystemPCIeFunction(App& app) :
- Node(
- app,
- "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/",
- std::string(), std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 2)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& device = params[0];
- const std::string& function = params[1];
-
- auto getPCIeDeviceCallback = [asyncResp, device, function](
- const boost::system::error_code ec,
- boost::container::flat_map<
- std::string,
- std::variant<std::string>>&
- pcieDevProperties) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG
- << "failed to get PCIe Device properties ec: " << ec.value()
- << ": " << ec.message();
- if (ec.value() ==
- boost::system::linux_error::bad_request_descriptor)
- {
- messages::resourceNotFound(asyncResp->res, "PCIeDevice",
- device);
- }
- else
- {
- messages::internalError(asyncResp->res);
- }
- return;
- }
-
- // Check if this function exists by looking for a device ID
- std::string devIDProperty = "Function" + function + "DeviceId";
- if (std::string* property =
- std::get_if<std::string>(&pcieDevProperties[devIDProperty]);
- property && property->empty())
- {
- messages::resourceNotFound(asyncResp->res, "PCIeFunction",
- function);
- return;
- }
-
- asyncResp->res.jsonValue = {
- {"@odata.type", "#PCIeFunction.v1_2_0.PCIeFunction"},
- {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" +
- device + "/PCIeFunctions/" + function},
- {"Name", "PCIe Function"},
- {"Id", function},
- {"FunctionId", std::stoi(function)},
- {"Links",
- {{"PCIeDevice",
- {{"@odata.id",
- "/redfish/v1/Systems/system/PCIeDevices/" + device}}}}}};
-
- if (std::string* property = std::get_if<std::string>(
- &pcieDevProperties["Function" + function + "DeviceId"]);
- property)
- {
- asyncResp->res.jsonValue["DeviceId"] = *property;
- }
-
- if (std::string* property = std::get_if<std::string>(
- &pcieDevProperties["Function" + function + "VendorId"]);
- property)
- {
- asyncResp->res.jsonValue["VendorId"] = *property;
- }
-
- if (std::string* property = std::get_if<std::string>(
- &pcieDevProperties["Function" + function + "FunctionType"]);
- property)
- {
- asyncResp->res.jsonValue["FunctionType"] = *property;
- }
-
- if (std::string* property = std::get_if<std::string>(
- &pcieDevProperties["Function" + function + "DeviceClass"]);
- property)
- {
- asyncResp->res.jsonValue["DeviceClass"] = *property;
- }
-
- if (std::string* property = std::get_if<std::string>(
- &pcieDevProperties["Function" + function + "ClassCode"]);
- property)
- {
- asyncResp->res.jsonValue["ClassCode"] = *property;
- }
-
- if (std::string* property = std::get_if<std::string>(
- &pcieDevProperties["Function" + function + "RevisionId"]);
- property)
- {
- asyncResp->res.jsonValue["RevisionId"] = *property;
- }
-
- if (std::string* property = std::get_if<std::string>(
- &pcieDevProperties["Function" + function + "SubsystemId"]);
- property)
- {
- asyncResp->res.jsonValue["SubsystemId"] = *property;
- }
-
- if (std::string* property = std::get_if<std::string>(
- &pcieDevProperties["Function" + function +
- "SubsystemVendorId"]);
- property)
- {
- asyncResp->res.jsonValue["SubsystemVendorId"] = *property;
- }
- };
- std::string escapedPath = std::string(pciePath) + "/" + device;
- dbus::utility::escapePathForDbus(escapedPath);
- crow::connections::systemBus->async_method_call(
- std::move(getPCIeDeviceCallback), pcieService, escapedPath,
- "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface);
- }
-};
+ std::string escapedPath = std::string(pciePath) + "/" + device;
+ dbus::utility::escapePathForDbus(escapedPath);
+ crow::connections::systemBus->async_method_call(
+ std::move(getPCIeDeviceCallback), pcieService, escapedPath,
+ "org.freedesktop.DBus.Properties", "GetAll",
+ pcieDeviceInterface);
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/power.hpp b/redfish-core/lib/power.hpp
index 4173ce8..3cc0224 100644
--- a/redfish-core/lib/power.hpp
+++ b/redfish-core/lib/power.hpp
@@ -16,35 +16,19 @@
*/
#pragma once
-#include "node.hpp"
#include "sensors.hpp"
+#include <app.hpp>
+
namespace redfish
{
-
-class Power : public Node
+void setPowerCapOverride(
+ const std::shared_ptr<SensorsAsyncResp>& sensorsAsyncResp,
+ std::vector<nlohmann::json>& powerControlCollections)
{
- public:
- Power(App& app) :
- Node((app), "/redfish/v1/Chassis/<str>/Power/", std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void setPowerCapOverride(
- const std::shared_ptr<SensorsAsyncResp>& sensorsAsyncResp,
- std::vector<nlohmann::json>& powerControlCollections)
- {
- auto getChassisPath = [sensorsAsyncResp, powerControlCollections](
- const std::optional<std::string>&
- chassisPath) mutable {
+ auto getChassisPath =
+ [sensorsAsyncResp, powerControlCollections](
+ const std::optional<std::string>& chassisPath) mutable {
if (!chassisPath)
{
BMCWEB_LOG_ERROR << "Don't find valid chassis path ";
@@ -138,235 +122,236 @@
"org.freedesktop.DBus.Properties", "Get",
"xyz.openbmc_project.Control.Power.Cap", "PowerCapEnable");
};
- getValidChassisPath(sensorsAsyncResp, std::move(getChassisPath));
- }
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 1)
- {
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
- const std::string& chassisName = params[0];
+ getValidChassisPath(sensorsAsyncResp, std::move(getChassisPath));
+}
+inline void requestRoutesPower(App& app)
+{
- asyncResp->res.jsonValue["PowerControl"] = nlohmann::json::array();
+ BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Power/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisName) {
+ asyncResp->res.jsonValue["PowerControl"] =
+ nlohmann::json::array();
- auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
- asyncResp, chassisName,
- sensors::dbus::paths.at(sensors::node::power),
- sensors::node::power);
+ auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
+ asyncResp, chassisName,
+ sensors::dbus::paths.at(sensors::node::power),
+ sensors::node::power);
- getChassisData(sensorAsyncResp);
+ getChassisData(sensorAsyncResp);
- // This callback verifies that the power limit is only provided for the
- // chassis that implements the Chassis inventory item. This prevents
- // things like power supplies providing the chassis power limit
- auto chassisHandler = [sensorAsyncResp](
- const boost::system::error_code e,
- const std::vector<std::string>&
- chassisPaths) {
- if (e)
- {
- BMCWEB_LOG_ERROR
- << "Power Limit GetSubTreePaths handler Dbus error " << e;
- return;
- }
-
- bool found = false;
- for (const std::string& chassis : chassisPaths)
- {
- size_t len = std::string::npos;
- size_t lastPos = chassis.rfind('/');
- if (lastPos == std::string::npos)
- {
- continue;
- }
-
- if (lastPos == chassis.size() - 1)
- {
- size_t end = lastPos;
- lastPos = chassis.rfind('/', lastPos - 1);
- if (lastPos == std::string::npos)
+ // This callback verifies that the power limit is only provided
+ // for the chassis that implements the Chassis inventory item.
+ // This prevents things like power supplies providing the
+ // chassis power limit
+ auto chassisHandler = [sensorAsyncResp](
+ const boost::system::error_code e,
+ const std::vector<std::string>&
+ chassisPaths) {
+ if (e)
{
- continue;
- }
-
- len = end - (lastPos + 1);
- }
-
- std::string interfaceChassisName =
- chassis.substr(lastPos + 1, len);
- if (!interfaceChassisName.compare(sensorAsyncResp->chassisId))
- {
- found = true;
- break;
- }
- }
-
- if (!found)
- {
- BMCWEB_LOG_DEBUG << "Power Limit not present for "
- << sensorAsyncResp->chassisId;
- return;
- }
-
- auto valueHandler =
- [sensorAsyncResp](
- const boost::system::error_code ec,
- const std::vector<std::pair<std::string, SensorVariant>>&
- properties) {
- if (ec)
- {
- messages::internalError(
- sensorAsyncResp->asyncResp->res);
BMCWEB_LOG_ERROR
- << "Power Limit GetAll handler: Dbus error " << ec;
+ << "Power Limit GetSubTreePaths handler Dbus error "
+ << e;
return;
}
- nlohmann::json& tempArray = sensorAsyncResp->asyncResp->res
- .jsonValue["PowerControl"];
-
- // Put multiple "sensors" into a single PowerControl, 0, so
- // only create the first one
- if (tempArray.empty())
+ bool found = false;
+ for (const std::string& chassis : chassisPaths)
{
- // Mandatory properties odata.id and MemberId
- // A warning without a odata.type
- tempArray.push_back(
- {{"@odata.type", "#Power.v1_0_0.PowerControl"},
- {"@odata.id", "/redfish/v1/Chassis/" +
- sensorAsyncResp->chassisId +
- "/Power#/PowerControl/0"},
- {"Name", "Chassis Power Control"},
- {"MemberId", "0"}});
- }
-
- nlohmann::json& sensorJson = tempArray.back();
- bool enabled = false;
- double powerCap = 0.0;
- int64_t scale = 0;
-
- for (const std::pair<std::string, SensorVariant>& property :
- properties)
- {
- if (!property.first.compare("Scale"))
+ size_t len = std::string::npos;
+ size_t lastPos = chassis.rfind('/');
+ if (lastPos == std::string::npos)
{
- const int64_t* i =
- std::get_if<int64_t>(&property.second);
-
- if (i)
- {
- scale = *i;
- }
+ continue;
}
- else if (!property.first.compare("PowerCap"))
- {
- const double* d =
- std::get_if<double>(&property.second);
- const int64_t* i =
- std::get_if<int64_t>(&property.second);
- const uint32_t* u =
- std::get_if<uint32_t>(&property.second);
- if (d)
+ if (lastPos == chassis.size() - 1)
+ {
+ size_t end = lastPos;
+ lastPos = chassis.rfind('/', lastPos - 1);
+ if (lastPos == std::string::npos)
{
- powerCap = *d;
+ continue;
}
- else if (i)
- {
- powerCap = static_cast<double>(*i);
- }
- else if (u)
- {
- powerCap = *u;
- }
+
+ len = end - (lastPos + 1);
}
- else if (!property.first.compare("PowerCapEnable"))
- {
- const bool* b = std::get_if<bool>(&property.second);
- if (b)
- {
- enabled = *b;
- }
+ std::string interfaceChassisName =
+ chassis.substr(lastPos + 1, len);
+ if (!interfaceChassisName.compare(
+ sensorAsyncResp->chassisId))
+ {
+ found = true;
+ break;
}
}
- nlohmann::json& value =
- sensorJson["PowerLimit"]["LimitInWatts"];
-
- // LimitException is Mandatory attribute as per OCP Baseline
- // Profile – v1.0.0, so currently making it "NoAction"
- // as default value to make it OCP Compliant.
- sensorJson["PowerLimit"]["LimitException"] = "NoAction";
-
- if (enabled)
+ if (!found)
{
- // Redfish specification indicates PowerLimit should be
- // null if the limit is not enabled.
- value = powerCap * std::pow(10, scale);
+ BMCWEB_LOG_DEBUG << "Power Limit not present for "
+ << sensorAsyncResp->chassisId;
+ return;
}
+
+ auto valueHandler = [sensorAsyncResp](
+ const boost::system::error_code ec,
+ const std::vector<std::pair<
+ std::string, SensorVariant>>&
+ properties) {
+ if (ec)
+ {
+ messages::internalError(
+ sensorAsyncResp->asyncResp->res);
+ BMCWEB_LOG_ERROR
+ << "Power Limit GetAll handler: Dbus error "
+ << ec;
+ return;
+ }
+
+ nlohmann::json& tempArray =
+ sensorAsyncResp->asyncResp->res
+ .jsonValue["PowerControl"];
+
+ // Put multiple "sensors" into a single PowerControl, 0,
+ // so only create the first one
+ if (tempArray.empty())
+ {
+ // Mandatory properties odata.id and MemberId
+ // A warning without a odata.type
+ tempArray.push_back(
+ {{"@odata.type", "#Power.v1_0_0.PowerControl"},
+ {"@odata.id", "/redfish/v1/Chassis/" +
+ sensorAsyncResp->chassisId +
+ "/Power#/PowerControl/0"},
+ {"Name", "Chassis Power Control"},
+ {"MemberId", "0"}});
+ }
+
+ nlohmann::json& sensorJson = tempArray.back();
+ bool enabled = false;
+ double powerCap = 0.0;
+ int64_t scale = 0;
+
+ for (const std::pair<std::string, SensorVariant>&
+ property : properties)
+ {
+ if (!property.first.compare("Scale"))
+ {
+ const int64_t* i =
+ std::get_if<int64_t>(&property.second);
+
+ if (i)
+ {
+ scale = *i;
+ }
+ }
+ else if (!property.first.compare("PowerCap"))
+ {
+ const double* d =
+ std::get_if<double>(&property.second);
+ const int64_t* i =
+ std::get_if<int64_t>(&property.second);
+ const uint32_t* u =
+ std::get_if<uint32_t>(&property.second);
+
+ if (d)
+ {
+ powerCap = *d;
+ }
+ else if (i)
+ {
+ powerCap = static_cast<double>(*i);
+ }
+ else if (u)
+ {
+ powerCap = *u;
+ }
+ }
+ else if (!property.first.compare("PowerCapEnable"))
+ {
+ const bool* b =
+ std::get_if<bool>(&property.second);
+
+ if (b)
+ {
+ enabled = *b;
+ }
+ }
+ }
+
+ nlohmann::json& value =
+ sensorJson["PowerLimit"]["LimitInWatts"];
+
+ // LimitException is Mandatory attribute as per OCP
+ // Baseline Profile – v1.0.0, so currently making it
+ // "NoAction" as default value to make it OCP Compliant.
+ sensorJson["PowerLimit"]["LimitException"] = "NoAction";
+
+ if (enabled)
+ {
+ // Redfish specification indicates PowerLimit should
+ // be null if the limit is not enabled.
+ value = powerCap * std::pow(10, scale);
+ }
+ };
+
+ crow::connections::systemBus->async_method_call(
+ std::move(valueHandler), "xyz.openbmc_project.Settings",
+ "/xyz/openbmc_project/control/host0/power_cap",
+ "org.freedesktop.DBus.Properties", "GetAll",
+ "xyz.openbmc_project.Control.Power.Cap");
};
- crow::connections::systemBus->async_method_call(
- std::move(valueHandler), "xyz.openbmc_project.Settings",
- "/xyz/openbmc_project/control/host0/power_cap",
- "org.freedesktop.DBus.Properties", "GetAll",
- "xyz.openbmc_project.Control.Power.Cap");
- };
+ crow::connections::systemBus->async_method_call(
+ std::move(chassisHandler),
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
+ "/xyz/openbmc_project/inventory", 0,
+ std::array<const char*, 2>{
+ "xyz.openbmc_project.Inventory.Item.Board",
+ "xyz.openbmc_project.Inventory.Item.Chassis"});
+ });
- crow::connections::systemBus->async_method_call(
- std::move(chassisHandler), "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
- "/xyz/openbmc_project/inventory", 0,
- std::array<const char*, 2>{
- "xyz.openbmc_project.Inventory.Item.Board",
- "xyz.openbmc_project.Inventory.Item.Chassis"});
- }
- void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Power/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::patch)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisName) {
+ auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
+ asyncResp, chassisName,
+ sensors::dbus::paths.at(sensors::node::power),
+ sensors::node::power);
- const std::string& chassisName = params[0];
+ std::optional<std::vector<nlohmann::json>> voltageCollections;
+ std::optional<std::vector<nlohmann::json>> powerCtlCollections;
- auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
- asyncResp, chassisName,
- sensors::dbus::paths.at(sensors::node::power),
- sensors::node::power);
+ if (!json_util::readJson(req, sensorAsyncResp->asyncResp->res,
+ "PowerControl", powerCtlCollections,
+ "Voltages", voltageCollections))
+ {
+ return;
+ }
- std::optional<std::vector<nlohmann::json>> voltageCollections;
- std::optional<std::vector<nlohmann::json>> powerCtlCollections;
-
- if (!json_util::readJson(req, sensorAsyncResp->asyncResp->res,
- "PowerControl", powerCtlCollections,
- "Voltages", voltageCollections))
- {
- return;
- }
-
- if (powerCtlCollections)
- {
- setPowerCapOverride(sensorAsyncResp, *powerCtlCollections);
- }
- if (voltageCollections)
- {
- std::unordered_map<std::string, std::vector<nlohmann::json>>
- allCollections;
- allCollections.emplace("Voltages", *std::move(voltageCollections));
- checkAndDoSensorsOverride(sensorAsyncResp, allCollections);
- }
- }
-};
+ if (powerCtlCollections)
+ {
+ setPowerCapOverride(sensorAsyncResp, *powerCtlCollections);
+ }
+ if (voltageCollections)
+ {
+ std::unordered_map<std::string, std::vector<nlohmann::json>>
+ allCollections;
+ allCollections.emplace("Voltages",
+ *std::move(voltageCollections));
+ checkAndDoSensorsOverride(sensorAsyncResp, allCollections);
+ }
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/processor.hpp b/redfish-core/lib/processor.hpp
index 49e04e2..8127510 100644
--- a/redfish-core/lib/processor.hpp
+++ b/redfish-core/lib/processor.hpp
@@ -17,8 +17,8 @@
#include "health.hpp"
+#include <app.hpp>
#include <boost/container/flat_map.hpp>
-#include <node.hpp>
#include <sdbusplus/message/native_types.hpp>
#include <sdbusplus/utility/dedup_variant.hpp>
#include <utils/collection.hpp>
@@ -981,281 +981,212 @@
std::variant<sdbusplus::message::object_path>(std::move(configPath)));
}
-class OperatingConfigCollection : public Node
+inline void requestRoutesOperatingConfigCollection(App& app)
{
- public:
- OperatingConfigCollection(App& app) :
- Node(app,
- "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/",
- std::string())
- {
- // Defined by Redfish spec privilege registry
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& cpuName) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#OperatingConfigCollection.OperatingConfigCollection";
+ asyncResp->res.jsonValue["@odata.id"] = req.url;
+ asyncResp->res.jsonValue["Name"] =
+ "Operating Config Collection";
- const std::string& cpuName = params[0];
- asyncResp->res.jsonValue["@odata.type"] =
- "#OperatingConfigCollection.OperatingConfigCollection";
- asyncResp->res.jsonValue["@odata.id"] = req.url;
- asyncResp->res.jsonValue["Name"] = "Operating Config Collection";
+ // First find the matching CPU object so we know how to
+ // constrain our search for related Config objects.
+ crow::connections::systemBus->async_method_call(
+ [asyncResp,
+ cpuName](const boost::system::error_code ec,
+ const std::vector<std::string>& objects) {
+ if (ec)
+ {
+ BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", "
+ << ec.message();
+ messages::internalError(asyncResp->res);
+ return;
+ }
- // First find the matching CPU object so we know how to constrain our
- // search for related Config objects.
- crow::connections::systemBus->async_method_call(
- [asyncResp, cpuName](const boost::system::error_code ec,
- const std::vector<std::string>& objects) {
- if (ec)
- {
- BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", "
- << ec.message();
- messages::internalError(asyncResp->res);
- return;
- }
+ for (const std::string& object : objects)
+ {
+ if (!boost::ends_with(object, cpuName))
+ {
+ continue;
+ }
- for (const std::string& object : objects)
- {
- if (!boost::ends_with(object, cpuName))
+ // Not expected that there will be multiple matching
+ // CPU objects, but if there are just use the first
+ // one.
+
+ // Use the common search routine to construct the
+ // Collection of all Config objects under this CPU.
+ collection_util::getCollectionMembers(
+ asyncResp,
+ "/redfish/v1/Systems/system/Processors/" +
+ cpuName + "/OperatingConfigs",
+ {"xyz.openbmc_project.Inventory.Item.Cpu."
+ "OperatingConfig"},
+ object.c_str());
+ return;
+ }
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
+ "/xyz/openbmc_project/inventory", 0,
+ std::array<const char*, 1>{
+ "xyz.openbmc_project.Control.Processor."
+ "CurrentOperatingConfig"});
+ });
+}
+
+inline void requestRoutesOperatingConfig(App& app)
+{
+ BMCWEB_ROUTE(
+ app,
+ "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/<str>/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::get)([](const crow::Request& req,
+ const std::shared_ptr<
+ bmcweb::AsyncResp>& asyncResp,
+ const std::string& cpuName,
+ const std::string& configName) {
+ // Ask for all objects implementing OperatingConfig so we can search
+ // for one with a matching name
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, cpuName, configName,
+ reqUrl{req.url}](boost::system::error_code ec,
+ const MapperGetSubTreeResponse& subtree) {
+ if (ec)
{
- continue;
+ BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", "
+ << ec.message();
+ messages::internalError(asyncResp->res);
+ return;
}
-
- // Not expected that there will be multiple matching CPU
- // objects, but if there are just use the first one.
-
- // Use the common search routine to construct the Collection
- // of all Config objects under this CPU.
- collection_util::getCollectionMembers(
- asyncResp,
- "/redfish/v1/Systems/system/Processors/" + cpuName +
- "/OperatingConfigs",
- {"xyz.openbmc_project.Inventory.Item.Cpu."
- "OperatingConfig"},
- object.c_str());
- return;
- }
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
- "/xyz/openbmc_project/inventory", 0,
- std::array<const char*, 1>{"xyz.openbmc_project.Control.Processor."
- "CurrentOperatingConfig"});
- }
-};
-
-class OperatingConfig : public Node
-{
- public:
- OperatingConfig(App& app) :
- Node(app,
- "/redfish/v1/Systems/system/Processors/<str>/OperatingConfigs/"
- "<str>/",
- std::string(), std::string())
- {
- // Defined by Redfish spec privilege registry
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 2)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- const std::string& cpuName = params[0];
- const std::string& configName = params[1];
-
- // Ask for all objects implementing OperatingConfig so we can search for
- // one with a matching name
- crow::connections::systemBus->async_method_call(
- [asyncResp, cpuName, configName,
- reqUrl{req.url}](boost::system::error_code ec,
- const MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", "
- << ec.message();
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string expectedEnding = cpuName + '/' + configName;
- for (const auto& [objectPath, serviceMap] : subtree)
- {
- // Ignore any configs without matching cpuX/configY
- if (!boost::ends_with(objectPath, expectedEnding) ||
- serviceMap.empty())
+ const std::string expectedEnding =
+ cpuName + '/' + configName;
+ for (const auto& [objectPath, serviceMap] : subtree)
{
- continue;
+ // Ignore any configs without matching cpuX/configY
+ if (!boost::ends_with(objectPath, expectedEnding) ||
+ serviceMap.empty())
+ {
+ continue;
+ }
+
+ nlohmann::json& json = asyncResp->res.jsonValue;
+ json["@odata.type"] =
+ "#OperatingConfig.v1_0_0.OperatingConfig";
+ json["@odata.id"] = reqUrl;
+ json["Name"] = "Processor Profile";
+ json["Id"] = configName;
+
+ // Just use the first implementation of the object - not
+ // expected that there would be multiple matching
+ // services
+ getOperatingConfigData(
+ asyncResp, serviceMap.begin()->first, objectPath);
+ return;
}
+ messages::resourceNotFound(asyncResp->res,
+ "OperatingConfig", configName);
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/inventory", 0,
+ std::array<const char*, 1>{
+ "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"});
+ });
+}
- nlohmann::json& json = asyncResp->res.jsonValue;
- json["@odata.type"] =
- "#OperatingConfig.v1_0_0.OperatingConfig";
- json["@odata.id"] = reqUrl;
- json["Name"] = "Processor Profile";
- json["Id"] = configName;
-
- // Just use the first implementation of the object - not
- // expected that there would be multiple matching services
- getOperatingConfigData(asyncResp, serviceMap.begin()->first,
- objectPath);
- return;
- }
- messages::resourceNotFound(asyncResp->res, "OperatingConfig",
- configName);
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTree",
- "/xyz/openbmc_project/inventory", 0,
- std::array<const char*, 1>{
- "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"});
- }
-};
-
-class ProcessorCollection : public Node
+inline void requestRoutesProcessorCollection(App& app)
{
- public:
- /*
- * Default Constructor
- */
- ProcessorCollection(App& app) :
- Node(app, "/redfish/v1/Systems/system/Processors/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
/**
* Functions triggers appropriate requests on DBus
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.type"] =
- "#ProcessorCollection.ProcessorCollection";
- asyncResp->res.jsonValue["Name"] = "Processor Collection";
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Processors/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#ProcessorCollection.ProcessorCollection";
+ asyncResp->res.jsonValue["Name"] = "Processor Collection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/Processors";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/Processors";
- collection_util::getCollectionMembers(
- asyncResp, "/redfish/v1/Systems/system/Processors",
- std::vector<const char*>(processorInterfaces.begin(),
- processorInterfaces.end()));
- }
-};
+ collection_util::getCollectionMembers(
+ asyncResp, "/redfish/v1/Systems/system/Processors",
+ std::vector<const char*>(processorInterfaces.begin(),
+ processorInterfaces.end()));
+ });
+}
-class Processor : public Node
+inline void requestRoutesProcessor(App& app)
{
- public:
- /*
- * Default Constructor
- */
- Processor(App& app) :
- Node(app, "/redfish/v1/Systems/system/Processors/<str>/", std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
/**
* Functions triggers appropriate requests on DBus
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- // Check if there is required param, truly entering this shall be
- // impossible
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& processorId = params[0];
- asyncResp->res.jsonValue["@odata.type"] =
- "#Processor.v1_11_0.Processor";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/Processors/" + processorId;
- getProcessorObject(asyncResp, processorId, getProcessorData);
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Processors/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& processorId) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#Processor.v1_11_0.Processor";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/Processors/" + processorId;
- void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>& params) override
- {
- std::optional<nlohmann::json> appliedConfigJson;
- if (!json_util::readJson(req, asyncResp->res, "AppliedOperatingConfig",
- appliedConfigJson))
- {
- return;
- }
+ getProcessorObject(asyncResp, processorId, getProcessorData);
+ });
- std::string appliedConfigUri;
- if (appliedConfigJson)
- {
- if (!json_util::readJson(*appliedConfigJson, asyncResp->res,
- "@odata.id", appliedConfigUri))
- {
- return;
- }
- // Check for 404 and find matching D-Bus object, then run property
- // patch handlers if that all succeeds.
- getProcessorObject(
- asyncResp, params[0],
- [appliedConfigUri = std::move(appliedConfigUri)](
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& processorId,
- const std::string& objectPath,
- const MapperServiceMap& serviceMap) {
- patchAppliedOperatingConfig(asyncResp, processorId,
- appliedConfigUri, objectPath,
- serviceMap);
- });
- }
- }
-};
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Processors/<str>/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::patch)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& processorId) {
+ std::optional<nlohmann::json> appliedConfigJson;
+ if (!json_util::readJson(req, asyncResp->res,
+ "AppliedOperatingConfig",
+ appliedConfigJson))
+ {
+ return;
+ }
+
+ std::string appliedConfigUri;
+ if (appliedConfigJson)
+ {
+ if (!json_util::readJson(*appliedConfigJson, asyncResp->res,
+ "@odata.id", appliedConfigUri))
+ {
+ return;
+ }
+ // Check for 404 and find matching D-Bus object, then run
+ // property patch handlers if that all succeeds.
+ getProcessorObject(
+ asyncResp, processorId,
+ [appliedConfigUri = std::move(appliedConfigUri)](
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& processorId,
+ const std::string& objectPath,
+ const MapperServiceMap& serviceMap) {
+ patchAppliedOperatingConfig(asyncResp, processorId,
+ appliedConfigUri,
+ objectPath, serviceMap);
+ });
+ }
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/redfish_sessions.hpp b/redfish-core/lib/redfish_sessions.hpp
index bef2753..3ae75ea 100644
--- a/redfish-core/lib/redfish_sessions.hpp
+++ b/redfish-core/lib/redfish_sessions.hpp
@@ -19,6 +19,8 @@
#include "node.hpp"
#include "persistent_data.hpp"
+#include <app.hpp>
+
namespace redfish
{
diff --git a/redfish-core/lib/redfish_util.hpp b/redfish-core/lib/redfish_util.hpp
index 620e977..5494a23 100644
--- a/redfish-core/lib/redfish_util.hpp
+++ b/redfish-core/lib/redfish_util.hpp
@@ -16,8 +16,6 @@
#ifndef BMCWEB_ENABLE_REDFISH_ONE_CHASSIS
#pragma once
-#include <node.hpp>
-
namespace redfish
{
diff --git a/redfish-core/lib/roles.hpp b/redfish-core/lib/roles.hpp
index 8e00d43..b375ff0 100644
--- a/redfish-core/lib/roles.hpp
+++ b/redfish-core/lib/roles.hpp
@@ -15,7 +15,7 @@
*/
#pragma once
-#include "node.hpp"
+#include <app.hpp>
#include <variant>
@@ -70,114 +70,86 @@
return true;
}
-class Roles : public Node
+inline void requestRoutesRoles(App& app)
{
- public:
- Roles(App& app) :
- Node(app, "/redfish/v1/AccountService/Roles/<str>/", std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Roles/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& roleId) {
+ nlohmann::json privArray = nlohmann::json::array();
+ if (false == getAssignedPrivFromRole(roleId, privArray))
+ {
+ messages::resourceNotFound(asyncResp->res, "Role", roleId);
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
+ return;
+ }
- return;
- }
- const std::string& roleId = params[0];
- nlohmann::json privArray = nlohmann::json::array();
- if (false == getAssignedPrivFromRole(roleId, privArray))
- {
- messages::resourceNotFound(asyncResp->res, "Role", roleId);
+ asyncResp->res.jsonValue = {
+ {"@odata.type", "#Role.v1_2_2.Role"},
+ {"Name", "User Role"},
+ {"Description", roleId + " User Role"},
+ {"OemPrivileges", nlohmann::json::array()},
+ {"IsPredefined", true},
+ {"Id", roleId},
+ {"RoleId", roleId},
+ {"@odata.id", "/redfish/v1/AccountService/Roles/" + roleId},
+ {"AssignedPrivileges", std::move(privArray)}};
+ });
+}
- return;
- }
-
- asyncResp->res.jsonValue = {
- {"@odata.type", "#Role.v1_2_2.Role"},
- {"Name", "User Role"},
- {"Description", roleId + " User Role"},
- {"OemPrivileges", nlohmann::json::array()},
- {"IsPredefined", true},
- {"Id", roleId},
- {"RoleId", roleId},
- {"@odata.id", "/redfish/v1/AccountService/Roles/" + roleId},
- {"AssignedPrivileges", std::move(privArray)}};
- }
-};
-
-class RoleCollection : public Node
+inline void requestRoutesRoleCollection(App& app)
{
- public:
- RoleCollection(App& app) : Node(app, "/redfish/v1/AccountService/Roles/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Roles/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue = {
+ {"@odata.id", "/redfish/v1/AccountService/Roles"},
+ {"@odata.type", "#RoleCollection.RoleCollection"},
+ {"Name", "Roles Collection"},
+ {"Description", "BMC User Roles"}};
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
-
- asyncResp->res.jsonValue = {
- {"@odata.id", "/redfish/v1/AccountService/Roles"},
- {"@odata.type", "#RoleCollection.RoleCollection"},
- {"Name", "Roles Collection"},
- {"Description", "BMC User Roles"}};
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](
+ const boost::system::error_code ec,
const std::variant<std::vector<std::string>>& resp) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- nlohmann::json& memberArray =
- asyncResp->res.jsonValue["Members"];
- memberArray = nlohmann::json::array();
- const std::vector<std::string>* privList =
- std::get_if<std::vector<std::string>>(&resp);
- if (privList == nullptr)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- for (const std::string& priv : *privList)
- {
- std::string role = getRoleFromPrivileges(priv);
- if (!role.empty())
- {
- memberArray.push_back(
- {{"@odata.id",
- "/redfish/v1/AccountService/Roles/" + role}});
- }
- }
- asyncResp->res.jsonValue["Members@odata.count"] =
- memberArray.size();
- },
- "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
- "org.freedesktop.DBus.Properties", "Get",
- "xyz.openbmc_project.User.Manager", "AllPrivileges");
- }
-};
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ nlohmann::json& memberArray =
+ asyncResp->res.jsonValue["Members"];
+ memberArray = nlohmann::json::array();
+ const std::vector<std::string>* privList =
+ std::get_if<std::vector<std::string>>(&resp);
+ if (privList == nullptr)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ for (const std::string& priv : *privList)
+ {
+ std::string role = getRoleFromPrivileges(priv);
+ if (!role.empty())
+ {
+ memberArray.push_back(
+ {{"@odata.id",
+ "/redfish/v1/AccountService/Roles/" +
+ role}});
+ }
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ memberArray.size();
+ },
+ "xyz.openbmc_project.User.Manager",
+ "/xyz/openbmc_project/user",
+ "org.freedesktop.DBus.Properties", "Get",
+ "xyz.openbmc_project.User.Manager", "AllPrivileges");
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp
index b20f7eb..0fc7e70 100644
--- a/redfish-core/lib/sensors.hpp
+++ b/redfish-core/lib/sensors.hpp
@@ -15,8 +15,7 @@
*/
#pragma once
-#include "node.hpp"
-
+#include <app.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/container/flat_map.hpp>
@@ -3106,177 +3105,142 @@
getChassisData(resp);
}
-class SensorCollection : public Node
+inline void requestRoutesSensorCollection(App& app)
{
- public:
- SensorCollection(App& app) :
- Node(app, "/redfish/v1/Chassis/<str>/Sensors/", std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Sensors/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::get)([](const crow::Request&,
+ const std::shared_ptr<
+ bmcweb::AsyncResp>& aResp,
+ const std::string& chassisId) {
+ BMCWEB_LOG_DEBUG << "SensorCollection doGet enter";
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- BMCWEB_LOG_DEBUG << "SensorCollection doGet enter";
- if (params.size() != 1)
- {
- BMCWEB_LOG_DEBUG << "SensorCollection doGet param size < 1";
- messages::internalError(aResp->res);
+ std::shared_ptr<SensorsAsyncResp> asyncResp =
+ std::make_shared<SensorsAsyncResp>(
+ aResp, chassisId,
+ sensors::dbus::paths.at(sensors::node::sensors),
+ sensors::node::sensors);
- return;
- }
+ auto getChassisCb =
+ [asyncResp](
+ const std::shared_ptr<
+ boost::container::flat_set<std::string>>& sensorNames) {
+ BMCWEB_LOG_DEBUG << "getChassisCb enter";
- const std::string& chassisId = params[0];
- std::shared_ptr<SensorsAsyncResp> asyncResp =
- std::make_shared<SensorsAsyncResp>(
- aResp, chassisId,
- sensors::dbus::paths.at(sensors::node::sensors),
- sensors::node::sensors);
-
- auto getChassisCb =
- [asyncResp](
- const std::shared_ptr<boost::container::flat_set<std::string>>&
- sensorNames) {
- BMCWEB_LOG_DEBUG << "getChassisCb enter";
-
- nlohmann::json& entriesArray =
- asyncResp->asyncResp->res.jsonValue["Members"];
- for (auto& sensor : *sensorNames)
- {
- BMCWEB_LOG_DEBUG << "Adding sensor: " << sensor;
-
- sdbusplus::message::object_path path(sensor);
- std::string sensorName = path.filename();
- if (sensorName.empty())
+ nlohmann::json& entriesArray =
+ asyncResp->asyncResp->res.jsonValue["Members"];
+ for (auto& sensor : *sensorNames)
{
- BMCWEB_LOG_ERROR << "Invalid sensor path: " << sensor;
- messages::internalError(asyncResp->asyncResp->res);
- return;
- }
- entriesArray.push_back(
- {{"@odata.id",
- "/redfish/v1/Chassis/" + asyncResp->chassisId + "/" +
- asyncResp->chassisSubNode + "/" + sensorName}});
- }
+ BMCWEB_LOG_DEBUG << "Adding sensor: " << sensor;
- asyncResp->asyncResp->res.jsonValue["Members@odata.count"] =
- entriesArray.size();
- BMCWEB_LOG_DEBUG << "getChassisCb exit";
- };
-
- // Get set of sensors in chassis
- getChassis(asyncResp, std::move(getChassisCb));
- BMCWEB_LOG_DEBUG << "SensorCollection doGet exit";
- }
-};
-
-class Sensor : public Node
-{
- public:
- Sensor(App& app) :
- Node(app, "/redfish/v1/Chassis/<str>/Sensors/<str>/", std::string(),
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- BMCWEB_LOG_DEBUG << "Sensor doGet enter";
- if (params.size() != 2)
- {
- BMCWEB_LOG_DEBUG << "Sensor doGet param size < 2";
- messages::internalError(aResp->res);
-
- return;
- }
- const std::string& chassisId = params[0];
- std::shared_ptr<SensorsAsyncResp> asyncResp =
- std::make_shared<SensorsAsyncResp>(aResp, chassisId,
- std::vector<const char*>(),
- sensors::node::sensors);
-
- const std::string& sensorName = params[1];
- const std::array<const char*, 1> interfaces = {
- "xyz.openbmc_project.Sensor.Value"};
-
- // Get a list of all of the sensors that implement Sensor.Value
- // and get the path and service name associated with the sensor
- crow::connections::systemBus->async_method_call(
- [asyncResp, sensorName](const boost::system::error_code ec,
- const GetSubTreeType& subtree) {
- BMCWEB_LOG_DEBUG << "respHandler1 enter";
- if (ec)
- {
- messages::internalError(asyncResp->asyncResp->res);
- BMCWEB_LOG_ERROR << "Sensor getSensorPaths resp_handler: "
- << "Dbus error " << ec;
- return;
- }
-
- GetSubTreeType::const_iterator it = std::find_if(
- subtree.begin(), subtree.end(),
- [sensorName](
- const std::pair<
- std::string,
- std::vector<std::pair<std::string,
- std::vector<std::string>>>>&
- object) {
- sdbusplus::message::object_path path(object.first);
- std::string name = path.filename();
- if (name.empty())
+ sdbusplus::message::object_path path(sensor);
+ std::string sensorName = path.filename();
+ if (sensorName.empty())
{
BMCWEB_LOG_ERROR << "Invalid sensor path: "
- << object.first;
- return false;
+ << sensor;
+ messages::internalError(asyncResp->asyncResp->res);
+ return;
}
+ entriesArray.push_back(
+ {{"@odata.id", "/redfish/v1/Chassis/" +
+ asyncResp->chassisId + "/" +
+ asyncResp->chassisSubNode + "/" +
+ sensorName}});
+ }
- return name == sensorName;
- });
+ asyncResp->asyncResp->res.jsonValue["Members@odata.count"] =
+ entriesArray.size();
+ BMCWEB_LOG_DEBUG << "getChassisCb exit";
+ };
- if (it == subtree.end())
- {
- BMCWEB_LOG_ERROR << "Could not find path for sensor: "
- << sensorName;
- messages::resourceNotFound(asyncResp->asyncResp->res,
- "Sensor", sensorName);
- return;
- }
- std::string_view sensorPath = (*it).first;
- BMCWEB_LOG_DEBUG << "Found sensor path for sensor '"
- << sensorName << "': " << sensorPath;
+ // Get set of sensors in chassis
+ getChassis(asyncResp, std::move(getChassisCb));
+ BMCWEB_LOG_DEBUG << "SensorCollection doGet exit";
+ });
+}
- const std::shared_ptr<boost::container::flat_set<std::string>>
- sensorList = std::make_shared<
- boost::container::flat_set<std::string>>();
+inline void requestRoutesSensor(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Sensors/<str>/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::get)([](const crow::Request&,
+ const std::shared_ptr<
+ bmcweb::AsyncResp>& aResp,
+ const std::string& chassisId,
+ const std::string& sensorName) {
+ BMCWEB_LOG_DEBUG << "Sensor doGet enter";
+ std::shared_ptr<SensorsAsyncResp> asyncResp =
+ std::make_shared<SensorsAsyncResp>(aResp, chassisId,
+ std::vector<const char*>(),
+ sensors::node::sensors);
- sensorList->emplace(sensorPath);
- processSensorList(asyncResp, sensorList);
- BMCWEB_LOG_DEBUG << "respHandler1 exit";
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTree",
- "/xyz/openbmc_project/sensors", 2, interfaces);
- }
-};
+ const std::array<const char*, 1> interfaces = {
+ "xyz.openbmc_project.Sensor.Value"};
+
+ // Get a list of all of the sensors that implement Sensor.Value
+ // and get the path and service name associated with the sensor
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, sensorName](const boost::system::error_code ec,
+ const GetSubTreeType& subtree) {
+ BMCWEB_LOG_DEBUG << "respHandler1 enter";
+ if (ec)
+ {
+ messages::internalError(asyncResp->asyncResp->res);
+ BMCWEB_LOG_ERROR
+ << "Sensor getSensorPaths resp_handler: "
+ << "Dbus error " << ec;
+ return;
+ }
+
+ GetSubTreeType::const_iterator it = std::find_if(
+ subtree.begin(), subtree.end(),
+ [sensorName](
+ const std::pair<
+ std::string,
+ std::vector<std::pair<
+ std::string, std::vector<std::string>>>>&
+ object) {
+ sdbusplus::message::object_path path(object.first);
+ std::string name = path.filename();
+ if (name.empty())
+ {
+ BMCWEB_LOG_ERROR << "Invalid sensor path: "
+ << object.first;
+ return false;
+ }
+
+ return name == sensorName;
+ });
+
+ if (it == subtree.end())
+ {
+ BMCWEB_LOG_ERROR << "Could not find path for sensor: "
+ << sensorName;
+ messages::resourceNotFound(asyncResp->asyncResp->res,
+ "Sensor", sensorName);
+ return;
+ }
+ std::string_view sensorPath = (*it).first;
+ BMCWEB_LOG_DEBUG << "Found sensor path for sensor '"
+ << sensorName << "': " << sensorPath;
+
+ const std::shared_ptr<
+ boost::container::flat_set<std::string>>
+ sensorList = std::make_shared<
+ boost::container::flat_set<std::string>>();
+
+ sensorList->emplace(sensorPath);
+ processSensorList(asyncResp, sensorList);
+ BMCWEB_LOG_DEBUG << "respHandler1 exit";
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/sensors", 2, interfaces);
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/service_root.hpp b/redfish-core/lib/service_root.hpp
index 06f9c84..df3e8d5 100644
--- a/redfish-core/lib/service_root.hpp
+++ b/redfish-core/lib/service_root.hpp
@@ -15,71 +15,57 @@
*/
#pragma once
-#include "node.hpp"
-
+#include <app.hpp>
#include <utils/systemd_utils.hpp>
namespace redfish
{
-class ServiceRoot : public Node
+inline void requestRoutesServiceRoot(App& app)
{
- public:
- ServiceRoot(App& app) : Node(app, "/redfish/v1/")
- {
- uuid = persistent_data::getConfig().systemUuid;
- entityPrivileges = {
- {boost::beast::http::verb::get, {}},
- {boost::beast::http::verb::head, {}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ std::string uuid = persistent_data::getConfig().systemUuid;
+ BMCWEB_ROUTE(app, "/redfish/v1/")
+ .privileges({})
+ .methods(boost::beast::http::verb::get)(
+ [uuid](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#ServiceRoot.v1_5_0.ServiceRoot";
+ asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1";
+ asyncResp->res.jsonValue["Id"] = "RootService";
+ asyncResp->res.jsonValue["Name"] = "Root Service";
+ asyncResp->res.jsonValue["RedfishVersion"] = "1.9.0";
+ asyncResp->res.jsonValue["Links"]["Sessions"] = {
+ {"@odata.id", "/redfish/v1/SessionService/Sessions"}};
+ asyncResp->res.jsonValue["AccountService"] = {
+ {"@odata.id", "/redfish/v1/AccountService"}};
+ asyncResp->res.jsonValue["Chassis"] = {
+ {"@odata.id", "/redfish/v1/Chassis"}};
+ asyncResp->res.jsonValue["JsonSchemas"] = {
+ {"@odata.id", "/redfish/v1/JsonSchemas"}};
+ asyncResp->res.jsonValue["Managers"] = {
+ {"@odata.id", "/redfish/v1/Managers"}};
+ asyncResp->res.jsonValue["SessionService"] = {
+ {"@odata.id", "/redfish/v1/SessionService"}};
+ asyncResp->res.jsonValue["Managers"] = {
+ {"@odata.id", "/redfish/v1/Managers"}};
+ asyncResp->res.jsonValue["Systems"] = {
+ {"@odata.id", "/redfish/v1/Systems"}};
+ asyncResp->res.jsonValue["Registries"] = {
+ {"@odata.id", "/redfish/v1/Registries"}};
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.type"] =
- "#ServiceRoot.v1_5_0.ServiceRoot";
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1";
- asyncResp->res.jsonValue["Id"] = "RootService";
- asyncResp->res.jsonValue["Name"] = "Root Service";
- asyncResp->res.jsonValue["RedfishVersion"] = "1.9.0";
- asyncResp->res.jsonValue["Links"]["Sessions"] = {
- {"@odata.id", "/redfish/v1/SessionService/Sessions"}};
- asyncResp->res.jsonValue["AccountService"] = {
- {"@odata.id", "/redfish/v1/AccountService"}};
- asyncResp->res.jsonValue["Chassis"] = {
- {"@odata.id", "/redfish/v1/Chassis"}};
- asyncResp->res.jsonValue["JsonSchemas"] = {
- {"@odata.id", "/redfish/v1/JsonSchemas"}};
- asyncResp->res.jsonValue["Managers"] = {
- {"@odata.id", "/redfish/v1/Managers"}};
- asyncResp->res.jsonValue["SessionService"] = {
- {"@odata.id", "/redfish/v1/SessionService"}};
- asyncResp->res.jsonValue["Managers"] = {
- {"@odata.id", "/redfish/v1/Managers"}};
- asyncResp->res.jsonValue["Systems"] = {
- {"@odata.id", "/redfish/v1/Systems"}};
- asyncResp->res.jsonValue["Registries"] = {
- {"@odata.id", "/redfish/v1/Registries"}};
-
- asyncResp->res.jsonValue["UpdateService"] = {
- {"@odata.id", "/redfish/v1/UpdateService"}};
- asyncResp->res.jsonValue["UUID"] = uuid;
- asyncResp->res.jsonValue["CertificateService"] = {
- {"@odata.id", "/redfish/v1/CertificateService"}};
- asyncResp->res.jsonValue["Tasks"] = {
- {"@odata.id", "/redfish/v1/TaskService"}};
- asyncResp->res.jsonValue["EventService"] = {
- {"@odata.id", "/redfish/v1/EventService"}};
- asyncResp->res.jsonValue["TelemetryService"] = {
- {"@odata.id", "/redfish/v1/TelemetryService"}};
- }
-
- std::string uuid;
-};
+ asyncResp->res.jsonValue["UpdateService"] = {
+ {"@odata.id", "/redfish/v1/UpdateService"}};
+ asyncResp->res.jsonValue["UUID"] = uuid;
+ asyncResp->res.jsonValue["CertificateService"] = {
+ {"@odata.id", "/redfish/v1/CertificateService"}};
+ asyncResp->res.jsonValue["Tasks"] = {
+ {"@odata.id", "/redfish/v1/TaskService"}};
+ asyncResp->res.jsonValue["EventService"] = {
+ {"@odata.id", "/redfish/v1/EventService"}};
+ asyncResp->res.jsonValue["TelemetryService"] = {
+ {"@odata.id", "/redfish/v1/TelemetryService"}};
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/storage.hpp b/redfish-core/lib/storage.hpp
index 34ef39a..0c3d9fd 100644
--- a/redfish-core/lib/storage.hpp
+++ b/redfish-core/lib/storage.hpp
@@ -18,197 +18,325 @@
#include "health.hpp"
#include "openbmc_dbus_rest.hpp"
-#include <node.hpp>
+#include <app.hpp>
namespace redfish
{
-class StorageCollection : public Node
+inline void requestRoutesStorageCollection(App& app)
{
- public:
- StorageCollection(App& app) :
- Node(app, "/redfish/v1/Systems/system/Storage/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Storage/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#StorageCollection.StorageCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/Storage";
+ asyncResp->res.jsonValue["Name"] = "Storage Collection";
+ asyncResp->res.jsonValue["Members"] = {
+ {{"@odata.id", "/redfish/v1/Systems/system/Storage/1"}}};
+ asyncResp->res.jsonValue["Members@odata.count"] = 1;
+ });
+}
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.type"] =
- "#StorageCollection.StorageCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/Storage";
- asyncResp->res.jsonValue["Name"] = "Storage Collection";
- asyncResp->res.jsonValue["Members"] = {
- {{"@odata.id", "/redfish/v1/Systems/system/Storage/1"}}};
- asyncResp->res.jsonValue["Members@odata.count"] = 1;
- }
-};
-
-class Storage : public Node
+inline void requestRoutesStorage(App& app)
{
- public:
- Storage(App& app) : Node(app, "/redfish/v1/Systems/system/Storage/1/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Storage/1/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::
+ get)([](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] = "#Storage.v1_7_1.Storage";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/Storage/1";
+ asyncResp->res.jsonValue["Name"] = "Storage";
+ asyncResp->res.jsonValue["Id"] = "1";
+ asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.type"] = "#Storage.v1_7_1.Storage";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/Storage/1";
- asyncResp->res.jsonValue["Name"] = "Storage";
- asyncResp->res.jsonValue["Id"] = "1";
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+ auto health = std::make_shared<HealthPopulate>(asyncResp);
+ health->populate();
- auto health = std::make_shared<HealthPopulate>(asyncResp);
- health->populate();
+ crow::connections::systemBus->async_method_call(
+ [asyncResp,
+ health](const boost::system::error_code ec,
+ const std::vector<std::string>& storageList) {
+ nlohmann::json& storageArray =
+ asyncResp->res.jsonValue["Drives"];
+ storageArray = nlohmann::json::array();
+ auto& count =
+ asyncResp->res.jsonValue["Drives@odata.count"];
+ count = 0;
- crow::connections::systemBus->async_method_call(
- [asyncResp, health](const boost::system::error_code ec,
- const std::vector<std::string>& storageList) {
- nlohmann::json& storageArray =
- asyncResp->res.jsonValue["Drives"];
- storageArray = nlohmann::json::array();
- auto& count = asyncResp->res.jsonValue["Drives@odata.count"];
- count = 0;
-
- if (ec)
- {
- BMCWEB_LOG_ERROR << "Drive mapper call error";
- messages::internalError(asyncResp->res);
- return;
- }
-
- health->inventory.insert(health->inventory.end(),
- storageList.begin(),
- storageList.end());
-
- for (const std::string& objpath : storageList)
- {
- std::size_t lastPos = objpath.rfind('/');
- if (lastPos == std::string::npos ||
- (objpath.size() <= lastPos + 1))
+ if (ec)
{
- BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath;
- continue;
- }
-
- storageArray.push_back(
- {{"@odata.id",
- "/redfish/v1/Systems/system/Storage/1/Drives/" +
- objpath.substr(lastPos + 1)}});
- }
-
- count = storageArray.size();
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
- "/xyz/openbmc_project/inventory", int32_t(0),
- std::array<const char*, 1>{
- "xyz.openbmc_project.Inventory.Item.Drive"});
-
- crow::connections::systemBus->async_method_call(
- [asyncResp,
- health](const boost::system::error_code ec,
- const crow::openbmc_mapper::GetSubTreeType& subtree) {
- if (ec || !subtree.size())
- {
- // doesn't have to be there
- return;
- }
-
- nlohmann::json& root =
- asyncResp->res.jsonValue["StorageControllers"];
- root = nlohmann::json::array();
- for (const auto& [path, interfaceDict] : subtree)
- {
- std::size_t lastPos = path.rfind('/');
- if (lastPos == std::string::npos ||
- (path.size() <= lastPos + 1))
- {
- BMCWEB_LOG_ERROR << "Failed to find '/' in " << path;
+ BMCWEB_LOG_ERROR << "Drive mapper call error";
+ messages::internalError(asyncResp->res);
return;
}
- if (interfaceDict.size() != 1)
+ health->inventory.insert(health->inventory.end(),
+ storageList.begin(),
+ storageList.end());
+
+ for (const std::string& objpath : storageList)
+ {
+ std::size_t lastPos = objpath.rfind('/');
+ if (lastPos == std::string::npos ||
+ (objpath.size() <= lastPos + 1))
+ {
+ BMCWEB_LOG_ERROR << "Failed to find '/' in "
+ << objpath;
+ continue;
+ }
+
+ storageArray.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Systems/system/Storage/1/Drives/" +
+ objpath.substr(lastPos + 1)}});
+ }
+
+ count = storageArray.size();
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
+ "/xyz/openbmc_project/inventory", int32_t(0),
+ std::array<const char*, 1>{
+ "xyz.openbmc_project.Inventory.Item.Drive"});
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp,
+ health](const boost::system::error_code ec,
+ const crow::openbmc_mapper::GetSubTreeType& subtree) {
+ if (ec || !subtree.size())
+ {
+ // doesn't have to be there
+ return;
+ }
+
+ nlohmann::json& root =
+ asyncResp->res.jsonValue["StorageControllers"];
+ root = nlohmann::json::array();
+ for (const auto& [path, interfaceDict] : subtree)
+ {
+ std::size_t lastPos = path.rfind('/');
+ if (lastPos == std::string::npos ||
+ (path.size() <= lastPos + 1))
+ {
+ BMCWEB_LOG_ERROR << "Failed to find '/' in "
+ << path;
+ return;
+ }
+
+ if (interfaceDict.size() != 1)
+ {
+ BMCWEB_LOG_ERROR << "Connection size "
+ << interfaceDict.size()
+ << ", greater than 1";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ const std::string& connectionName =
+ interfaceDict.front().first;
+
+ size_t index = root.size();
+ nlohmann::json& storageController =
+ root.emplace_back(nlohmann::json::object());
+
+ std::string id = path.substr(lastPos + 1);
+
+ storageController["@odata.type"] =
+ "#Storage.v1_7_0.StorageController";
+ storageController["@odata.id"] =
+ "/redfish/v1/Systems/system/Storage/1"
+ "#/StorageControllers/" +
+ std::to_string(index);
+ storageController["Name"] = id;
+ storageController["MemberId"] = id;
+ storageController["Status"]["State"] = "Enabled";
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp,
+ index](const boost::system::error_code ec2,
+ const std::variant<bool> present) {
+ // this interface isn't necessary, only check it
+ // if we get a good return
+ if (ec2)
+ {
+ return;
+ }
+ const bool* enabled =
+ std::get_if<bool>(&present);
+ if (enabled == nullptr)
+ {
+ BMCWEB_LOG_DEBUG
+ << "Illegal property present";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (!(*enabled))
+ {
+ asyncResp->res
+ .jsonValue["StorageControllers"][index]
+ ["Status"]["State"] =
+ "Disabled";
+ }
+ },
+ connectionName, path,
+ "org.freedesktop.DBus.Properties", "Get",
+ "xyz.openbmc_project.Inventory.Item", "Present");
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, index](
+ const boost::system::error_code ec2,
+ const std::vector<std::pair<
+ std::string,
+ std::variant<bool, std::string, uint64_t>>>&
+ propertiesList) {
+ if (ec2)
+ {
+ // this interface isn't necessary
+ return;
+ }
+ for (const std::pair<
+ std::string,
+ std::variant<bool, std::string,
+ uint64_t>>& property :
+ propertiesList)
+ {
+ // Store DBus properties that are also
+ // Redfish properties with same name and a
+ // string value
+ const std::string& propertyName =
+ property.first;
+ nlohmann::json& object =
+ asyncResp->res
+ .jsonValue["StorageControllers"]
+ [index];
+ if ((propertyName == "PartNumber") ||
+ (propertyName == "SerialNumber") ||
+ (propertyName == "Manufacturer") ||
+ (propertyName == "Model"))
+ {
+ const std::string* value =
+ std::get_if<std::string>(
+ &property.second);
+ if (value == nullptr)
+ {
+ // illegal property
+ messages::internalError(
+ asyncResp->res);
+ return;
+ }
+ object[propertyName] = *value;
+ }
+ }
+ },
+ connectionName, path,
+ "org.freedesktop.DBus.Properties", "GetAll",
+ "xyz.openbmc_project.Inventory.Decorator.Asset");
+ }
+
+ // this is done after we know the json array will no longer
+ // be resized, as json::array uses vector underneath and we
+ // need references to its members that won't change
+ size_t count = 0;
+ for (const auto& [path, interfaceDict] : subtree)
+ {
+ auto subHealth = std::make_shared<HealthPopulate>(
+ asyncResp, root[count]["Status"]);
+ subHealth->inventory.emplace_back(path);
+ health->inventory.emplace_back(path);
+ health->children.emplace_back(subHealth);
+ count++;
+ }
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/inventory", int32_t(0),
+ std::array<const char*, 1>{
+ "xyz.openbmc_project.Inventory.Item.StorageController"});
+ });
+}
+
+inline void requestRoutesDrive(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Storage/1/Drives/<str>/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::get)([](const crow::Request&,
+ const std::shared_ptr<
+ bmcweb::AsyncResp>& asyncResp,
+ const std::string& driveId) {
+ crow::connections::systemBus->async_method_call(
+ [asyncResp,
+ driveId](const boost::system::error_code ec,
+ const crow::openbmc_mapper::GetSubTreeType& subtree) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "Drive mapper call error";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ auto object2 = std::find_if(
+ subtree.begin(), subtree.end(),
+ [&driveId](auto& object) {
+ const std::string& path = object.first;
+ return boost::ends_with(path, "/" + driveId);
+ });
+
+ if (object2 == subtree.end())
+ {
+ messages::resourceNotFound(asyncResp->res, "Drive",
+ driveId);
+ return;
+ }
+
+ const std::string& path = object2->first;
+ const std::vector<
+ std::pair<std::string, std::vector<std::string>>>&
+ connectionNames = object2->second;
+
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#Drive.v1_7_0.Drive";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/Storage/1/Drives/" +
+ driveId;
+ asyncResp->res.jsonValue["Name"] = driveId;
+ asyncResp->res.jsonValue["Id"] = driveId;
+
+ if (connectionNames.size() != 1)
{
BMCWEB_LOG_ERROR << "Connection size "
- << interfaceDict.size()
+ << connectionNames.size()
<< ", greater than 1";
messages::internalError(asyncResp->res);
return;
}
+ getMainChassisId(
+ asyncResp,
+ [](const std::string& chassisId,
+ const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
+ aRsp->res.jsonValue["Links"]["Chassis"] = {
+ {"@odata.id",
+ "/redfish/v1/Chassis/" + chassisId}};
+ });
+
const std::string& connectionName =
- interfaceDict.front().first;
-
- size_t index = root.size();
- nlohmann::json& storageController =
- root.emplace_back(nlohmann::json::object());
-
- std::string id = path.substr(lastPos + 1);
-
- storageController["@odata.type"] =
- "#Storage.v1_7_0.StorageController";
- storageController["@odata.id"] =
- "/redfish/v1/Systems/system/Storage/1"
- "#/StorageControllers/" +
- std::to_string(index);
- storageController["Name"] = id;
- storageController["MemberId"] = id;
- storageController["Status"]["State"] = "Enabled";
-
+ connectionNames[0].first;
crow::connections::systemBus->async_method_call(
- [asyncResp, index](const boost::system::error_code ec2,
- const std::variant<bool> present) {
- // this interface isn't necessary, only check it if
- // we get a good return
- if (ec2)
- {
- return;
- }
- const bool* enabled = std::get_if<bool>(&present);
- if (enabled == nullptr)
- {
- BMCWEB_LOG_DEBUG << "Illegal property present";
- messages::internalError(asyncResp->res);
- return;
- }
- if (!(*enabled))
- {
- asyncResp->res
- .jsonValue["StorageControllers"][index]
- ["Status"]["State"] = "Disabled";
- }
- },
- connectionName, path, "org.freedesktop.DBus.Properties",
- "Get", "xyz.openbmc_project.Inventory.Item", "Present");
-
- crow::connections::systemBus->async_method_call(
- [asyncResp,
- index](const boost::system::error_code ec2,
- const std::vector<std::pair<
- std::string,
- std::variant<bool, std::string, uint64_t>>>&
- propertiesList) {
+ [asyncResp](
+ const boost::system::error_code ec2,
+ const std::vector<std::pair<
+ std::string,
+ std::variant<bool, std::string, uint64_t>>>&
+ propertiesList) {
if (ec2)
{
// this interface isn't necessary
@@ -224,9 +352,6 @@
// string value
const std::string& propertyName =
property.first;
- nlohmann::json& object =
- asyncResp->res
- .jsonValue["StorageControllers"][index];
if ((propertyName == "PartNumber") ||
(propertyName == "SerialNumber") ||
(propertyName == "Manufacturer") ||
@@ -241,226 +366,84 @@
messages::internalError(asyncResp->res);
return;
}
- object[propertyName] = *value;
+ asyncResp->res.jsonValue[propertyName] =
+ *value;
}
}
},
connectionName, path, "org.freedesktop.DBus.Properties",
"GetAll",
"xyz.openbmc_project.Inventory.Decorator.Asset");
- }
- // this is done after we know the json array will no longer be
- // resized, as json::array uses vector underneath and we need
- // references to its members that won't change
- size_t count = 0;
- for (const auto& [path, interfaceDict] : subtree)
- {
- auto subHealth = std::make_shared<HealthPopulate>(
- asyncResp, root[count]["Status"]);
- subHealth->inventory.emplace_back(path);
+ // default it to Enabled
+ asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+
+ auto health = std::make_shared<HealthPopulate>(asyncResp);
health->inventory.emplace_back(path);
- health->children.emplace_back(subHealth);
- count++;
- }
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTree",
- "/xyz/openbmc_project/inventory", int32_t(0),
- std::array<const char*, 1>{
- "xyz.openbmc_project.Inventory.Item.StorageController"});
- }
-};
+ health->populate();
-class Drive : public Node
-{
- public:
- Drive(App& app) :
- Node(app, "/redfish/v1/Systems/system/Storage/1/Drives/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& driveId = params[0];
-
- crow::connections::systemBus->async_method_call(
- [asyncResp,
- driveId](const boost::system::error_code ec,
- const crow::openbmc_mapper::GetSubTreeType& subtree) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "Drive mapper call error";
- messages::internalError(asyncResp->res);
- return;
- }
-
- auto object2 = std::find_if(
- subtree.begin(), subtree.end(), [&driveId](auto& object) {
- const std::string& path = object.first;
- return boost::ends_with(path, "/" + driveId);
- });
-
- if (object2 == subtree.end())
- {
- messages::resourceNotFound(asyncResp->res, "Drive",
- driveId);
- return;
- }
-
- const std::string& path = object2->first;
- const std::vector<
- std::pair<std::string, std::vector<std::string>>>&
- connectionNames = object2->second;
-
- asyncResp->res.jsonValue["@odata.type"] = "#Drive.v1_7_0.Drive";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/Storage/1/Drives/" + driveId;
- asyncResp->res.jsonValue["Name"] = driveId;
- asyncResp->res.jsonValue["Id"] = driveId;
-
- if (connectionNames.size() != 1)
- {
- BMCWEB_LOG_ERROR << "Connection size "
- << connectionNames.size()
- << ", greater than 1";
- messages::internalError(asyncResp->res);
- return;
- }
-
- getMainChassisId(
- asyncResp,
- [](const std::string& chassisId,
- const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
- aRsp->res.jsonValue["Links"]["Chassis"] = {
- {"@odata.id", "/redfish/v1/Chassis/" + chassisId}};
- });
-
- const std::string& connectionName = connectionNames[0].first;
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec2,
- const std::vector<std::pair<
- std::string,
- std::variant<bool, std::string, uint64_t>>>&
- propertiesList) {
- if (ec2)
- {
- // this interface isn't necessary
- return;
- }
- for (const std::pair<std::string,
- std::variant<bool, std::string,
- uint64_t>>& property :
- propertiesList)
- {
- // Store DBus properties that are also
- // Redfish properties with same name and a
- // string value
- const std::string& propertyName = property.first;
- if ((propertyName == "PartNumber") ||
- (propertyName == "SerialNumber") ||
- (propertyName == "Manufacturer") ||
- (propertyName == "Model"))
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, path](const boost::system::error_code ec2,
+ const std::variant<bool> present) {
+ // this interface isn't necessary, only check it if
+ // we get a good return
+ if (ec2)
{
- const std::string* value =
- std::get_if<std::string>(&property.second);
- if (value == nullptr)
- {
- // illegal property
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue[propertyName] = *value;
+ return;
}
- }
- },
- connectionName, path, "org.freedesktop.DBus.Properties",
- "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset");
+ const bool* enabled = std::get_if<bool>(&present);
+ if (enabled == nullptr)
+ {
+ BMCWEB_LOG_DEBUG << "Illegal property present";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (!(*enabled))
+ {
+ asyncResp->res.jsonValue["Status"]["State"] =
+ "Disabled";
+ }
+ },
+ connectionName, path, "org.freedesktop.DBus.Properties",
+ "Get", "xyz.openbmc_project.Inventory.Item", "Present");
- // default it to Enabled
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec2,
+ const std::variant<bool> rebuilding) {
+ // this interface isn't necessary, only check it if
+ // we get a good return
+ if (ec2)
+ {
+ return;
+ }
+ const bool* updating =
+ std::get_if<bool>(&rebuilding);
+ if (updating == nullptr)
+ {
+ BMCWEB_LOG_DEBUG << "Illegal property present";
+ messages::internalError(asyncResp->res);
+ return;
+ }
- auto health = std::make_shared<HealthPopulate>(asyncResp);
- health->inventory.emplace_back(path);
- health->populate();
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, path](const boost::system::error_code ec2,
- const std::variant<bool> present) {
- // this interface isn't necessary, only check it if we
- // get a good return
- if (ec2)
- {
- return;
- }
- const bool* enabled = std::get_if<bool>(&present);
- if (enabled == nullptr)
- {
- BMCWEB_LOG_DEBUG << "Illegal property present";
- messages::internalError(asyncResp->res);
- return;
- }
- if (!(*enabled))
- {
- asyncResp->res.jsonValue["Status"]["State"] =
- "Disabled";
- }
- },
- connectionName, path, "org.freedesktop.DBus.Properties",
- "Get", "xyz.openbmc_project.Inventory.Item", "Present");
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec2,
- const std::variant<bool> rebuilding) {
- // this interface isn't necessary, only check it if we
- // get a good return
- if (ec2)
- {
- return;
- }
- const bool* updating = std::get_if<bool>(&rebuilding);
- if (updating == nullptr)
- {
- BMCWEB_LOG_DEBUG << "Illegal property present";
- messages::internalError(asyncResp->res);
- return;
- }
-
- // updating and disabled in the backend shouldn't be
- // able to be set at the same time, so we don't need to
- // check for the race condition of these two calls
- if ((*updating))
- {
- asyncResp->res.jsonValue["Status"]["State"] =
- "Updating";
- }
- },
- connectionName, path, "org.freedesktop.DBus.Properties",
- "Get", "xyz.openbmc_project.State.Drive", "Rebuilding");
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTree",
- "/xyz/openbmc_project/inventory", int32_t(0),
- std::array<const char*, 1>{
- "xyz.openbmc_project.Inventory.Item.Drive"});
- }
-};
+ // updating and disabled in the backend shouldn't be
+ // able to be set at the same time, so we don't need
+ // to check for the race condition of these two
+ // calls
+ if ((*updating))
+ {
+ asyncResp->res.jsonValue["Status"]["State"] =
+ "Updating";
+ }
+ },
+ connectionName, path, "org.freedesktop.DBus.Properties",
+ "Get", "xyz.openbmc_project.State.Drive", "Rebuilding");
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/inventory", int32_t(0),
+ std::array<const char*, 1>{
+ "xyz.openbmc_project.Inventory.Item.Drive"});
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
index 13cbcf3..2656a20 100644
--- a/redfish-core/lib/systems.hpp
+++ b/redfish-core/lib/systems.hpp
@@ -20,8 +20,8 @@
#include "pcie.hpp"
#include "redfish_util.hpp"
+#include <app.hpp>
#include <boost/container/flat_map.hpp>
-#include <node.hpp>
#include <utils/fw_utils.hpp>
#include <utils/json_utils.hpp>
@@ -1858,456 +1858,426 @@
* SystemsCollection derived class for delivering ComputerSystems Collection
* Schema
*/
-class SystemsCollection : public Node
+inline void requestRoutesSystemsCollection(App& app)
{
- public:
- SystemsCollection(App& app) : Node(app, "/redfish/v1/Systems/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#ComputerSystemCollection.ComputerSystemCollection";
+ asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
+ asyncResp->res.jsonValue["Name"] = "Computer System Collection";
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.type"] =
- "#ComputerSystemCollection.ComputerSystemCollection";
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
- asyncResp->res.jsonValue["Name"] = "Computer System Collection";
+ crow::connections::systemBus->async_method_call(
+ [asyncResp,
+ &req](const boost::system::error_code ec,
+ const std::variant<std::string>& /*hostName*/) {
+ nlohmann::json& ifaceArray =
+ asyncResp->res.jsonValue["Members"];
+ ifaceArray = nlohmann::json::array();
+ auto& count =
+ asyncResp->res.jsonValue["Members@odata.count"];
+ ifaceArray.push_back(
+ {{"@odata.id", "/redfish/v1/Systems/system"}});
+ count = ifaceArray.size();
+ if (!ec)
+ {
+ BMCWEB_LOG_DEBUG << "Hypervisor is available";
+ ifaceArray.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Systems/hypervisor"}});
+ count = ifaceArray.size();
+ }
+ },
+ "xyz.openbmc_project.Settings",
+ "/xyz/openbmc_project/network/hypervisor",
+ "org.freedesktop.DBus.Properties", "Get",
+ "xyz.openbmc_project.Network.SystemConfiguration",
+ "HostName");
+ });
+}
- crow::connections::systemBus->async_method_call(
- [asyncResp, &req](const boost::system::error_code ec,
- const std::variant<std::string>& /*hostName*/) {
- nlohmann::json& ifaceArray =
- asyncResp->res.jsonValue["Members"];
- ifaceArray = nlohmann::json::array();
- auto& count = asyncResp->res.jsonValue["Members@odata.count"];
- ifaceArray.push_back(
- {{"@odata.id", "/redfish/v1/Systems/system"}});
- count = ifaceArray.size();
- if (!ec)
- {
- BMCWEB_LOG_DEBUG << "Hypervisor is available";
- ifaceArray.push_back(
- {{"@odata.id", "/redfish/v1/Systems/hypervisor"}});
- count = ifaceArray.size();
- }
- },
- "xyz.openbmc_project.Settings",
- "/xyz/openbmc_project/network/hypervisor",
- "org.freedesktop.DBus.Properties", "Get",
- "xyz.openbmc_project.Network.SystemConfiguration", "HostName");
- }
-};
+/**
+ * Function transceives data with dbus directly.
+ */
+void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
+ constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
+ constexpr char const* interfaceName =
+ "xyz.openbmc_project.Control.Host.NMI";
+ constexpr char const* method = "NMI";
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ messages::success(asyncResp->res);
+ },
+ serviceName, objectPath, interfaceName, method);
+}
/**
* SystemActionsReset class supports handle POST method for Reset action.
* The class retrieves and sends data directly to D-Bus.
*/
-class SystemActionsReset : public Node
+inline void requestRoutesSystemActionsReset(App& app)
{
- public:
- SystemActionsReset(App& app) :
- Node(app, "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
/**
* Function handles POST method request.
* Analyzes POST body message before sends Reset request data to D-Bus.
*/
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
+ .privileges({"ConfigureComponent"})
+ .methods(
+ boost::beast::http::verb::
+ post)([](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ std::string resetType;
+ if (!json_util::readJson(req, asyncResp->res, "ResetType",
+ resetType))
+ {
+ return;
+ }
- std::string resetType;
- if (!json_util::readJson(req, asyncResp->res, "ResetType", resetType))
- {
- return;
- }
+ // Get the command and host vs. chassis
+ std::string command;
+ bool hostCommand;
+ if ((resetType == "On") || (resetType == "ForceOn"))
+ {
+ command = "xyz.openbmc_project.State.Host.Transition.On";
+ hostCommand = true;
+ }
+ else if (resetType == "ForceOff")
+ {
+ command = "xyz.openbmc_project.State.Chassis.Transition.Off";
+ hostCommand = false;
+ }
+ else if (resetType == "ForceRestart")
+ {
+ command =
+ "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
+ hostCommand = true;
+ }
+ else if (resetType == "GracefulShutdown")
+ {
+ command = "xyz.openbmc_project.State.Host.Transition.Off";
+ hostCommand = true;
+ }
+ else if (resetType == "GracefulRestart")
+ {
+ command = "xyz.openbmc_project.State.Host.Transition."
+ "GracefulWarmReboot";
+ hostCommand = true;
+ }
+ else if (resetType == "PowerCycle")
+ {
+ command = "xyz.openbmc_project.State.Host.Transition.Reboot";
+ hostCommand = true;
+ }
+ else if (resetType == "Nmi")
+ {
+ doNMI(asyncResp);
+ return;
+ }
+ else
+ {
+ messages::actionParameterUnknown(asyncResp->res, "Reset",
+ resetType);
+ return;
+ }
- // Get the command and host vs. chassis
- std::string command;
- bool hostCommand;
- if ((resetType == "On") || (resetType == "ForceOn"))
- {
- command = "xyz.openbmc_project.State.Host.Transition.On";
- hostCommand = true;
- }
- else if (resetType == "ForceOff")
- {
- command = "xyz.openbmc_project.State.Chassis.Transition.Off";
- hostCommand = false;
- }
- else if (resetType == "ForceRestart")
- {
- command =
- "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
- hostCommand = true;
- }
- else if (resetType == "GracefulShutdown")
- {
- command = "xyz.openbmc_project.State.Host.Transition.Off";
- hostCommand = true;
- }
- else if (resetType == "GracefulRestart")
- {
- command =
- "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
- hostCommand = true;
- }
- else if (resetType == "PowerCycle")
- {
- command = "xyz.openbmc_project.State.Host.Transition.Reboot";
- hostCommand = true;
- }
- else if (resetType == "Nmi")
- {
- doNMI(asyncResp);
- return;
- }
- else
- {
- messages::actionParameterUnknown(asyncResp->res, "Reset",
- resetType);
- return;
- }
-
- if (hostCommand)
- {
- crow::connections::systemBus->async_method_call(
- [asyncResp, resetType](const boost::system::error_code ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
- if (ec.value() == boost::asio::error::invalid_argument)
+ if (hostCommand)
+ {
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, resetType](const boost::system::error_code ec) {
+ if (ec)
{
- messages::actionParameterNotSupported(
- asyncResp->res, resetType, "Reset");
+ BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
+ if (ec.value() ==
+ boost::asio::error::invalid_argument)
+ {
+ messages::actionParameterNotSupported(
+ asyncResp->res, resetType, "Reset");
+ }
+ else
+ {
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- else
+ messages::success(asyncResp->res);
+ },
+ "xyz.openbmc_project.State.Host",
+ "/xyz/openbmc_project/state/host0",
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.State.Host", "RequestedHostTransition",
+ std::variant<std::string>{command});
+ }
+ else
+ {
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, resetType](const boost::system::error_code ec) {
+ if (ec)
{
- messages::internalError(asyncResp->res);
+ BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
+ if (ec.value() ==
+ boost::asio::error::invalid_argument)
+ {
+ messages::actionParameterNotSupported(
+ asyncResp->res, resetType, "Reset");
+ }
+ else
+ {
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- messages::success(asyncResp->res);
- },
- "xyz.openbmc_project.State.Host",
- "/xyz/openbmc_project/state/host0",
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.State.Host", "RequestedHostTransition",
- std::variant<std::string>{command});
- }
- else
- {
- crow::connections::systemBus->async_method_call(
- [asyncResp, resetType](const boost::system::error_code ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
- if (ec.value() == boost::asio::error::invalid_argument)
- {
- messages::actionParameterNotSupported(
- asyncResp->res, resetType, "Reset");
- }
- else
- {
- messages::internalError(asyncResp->res);
- }
- return;
- }
- messages::success(asyncResp->res);
- },
- "xyz.openbmc_project.State.Chassis",
- "/xyz/openbmc_project/state/chassis0",
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
- std::variant<std::string>{command});
- }
- }
- /**
- * Function transceives data with dbus directly.
- */
- void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
- {
- constexpr char const* serviceName =
- "xyz.openbmc_project.Control.Host.NMI";
- constexpr char const* objectPath =
- "/xyz/openbmc_project/control/host0/nmi";
- constexpr char const* interfaceName =
- "xyz.openbmc_project.Control.Host.NMI";
- constexpr char const* method = "NMI";
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
- messages::success(asyncResp->res);
- },
- serviceName, objectPath, interfaceName, method);
- }
-};
+ messages::success(asyncResp->res);
+ },
+ "xyz.openbmc_project.State.Chassis",
+ "/xyz/openbmc_project/state/chassis0",
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.State.Chassis",
+ "RequestedPowerTransition",
+ std::variant<std::string>{command});
+ }
+ });
+}
/**
* Systems derived class for delivering Computer Systems Schema.
*/
-class Systems : public Node
+inline void requestRoutesSystems(App& app)
{
- public:
- /*
- * Default Constructor
- */
- Systems(App& app) : Node(app, "/redfish/v1/Systems/system/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
- private:
/**
* Functions triggers appropriate requests on DBus
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.type"] =
- "#ComputerSystem.v1_13_0.ComputerSystem";
- asyncResp->res.jsonValue["Name"] = "system";
- asyncResp->res.jsonValue["Id"] = "system";
- asyncResp->res.jsonValue["SystemType"] = "Physical";
- asyncResp->res.jsonValue["Description"] = "Computer System";
- asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
- asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
- "Disabled";
- asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
- uint64_t(0);
- asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
- "Disabled";
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::
+ get)([](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#ComputerSystem.v1_13_0.ComputerSystem";
+ asyncResp->res.jsonValue["Name"] = "system";
+ asyncResp->res.jsonValue["Id"] = "system";
+ asyncResp->res.jsonValue["SystemType"] = "Physical";
+ asyncResp->res.jsonValue["Description"] = "Computer System";
+ asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
+ asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
+ "Disabled";
+ asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
+ uint64_t(0);
+ asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
+ "Disabled";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system";
- asyncResp->res.jsonValue["Processors"] = {
- {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
- asyncResp->res.jsonValue["Memory"] = {
- {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
- asyncResp->res.jsonValue["Storage"] = {
- {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
+ asyncResp->res.jsonValue["Processors"] = {
+ {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
+ asyncResp->res.jsonValue["Memory"] = {
+ {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
+ asyncResp->res.jsonValue["Storage"] = {
+ {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
- asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
- {"target",
- "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
- {"@Redfish.ActionInfo",
- "/redfish/v1/Systems/system/ResetActionInfo"}};
+ asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
+ {"target",
+ "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
+ {"@Redfish.ActionInfo",
+ "/redfish/v1/Systems/system/ResetActionInfo"}};
- asyncResp->res.jsonValue["LogServices"] = {
- {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
+ asyncResp->res.jsonValue["LogServices"] = {
+ {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
- asyncResp->res.jsonValue["Bios"] = {
- {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
+ asyncResp->res.jsonValue["Bios"] = {
+ {"@odata.id", "/redfish/v1/Systems/system/Bios"}};
- asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
- {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
+ asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
+ {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
- asyncResp->res.jsonValue["Status"] = {
- {"Health", "OK"},
- {"State", "Enabled"},
- };
- constexpr const std::array<const char*, 4> inventoryForSystems = {
- "xyz.openbmc_project.Inventory.Item.Dimm",
- "xyz.openbmc_project.Inventory.Item.Cpu",
- "xyz.openbmc_project.Inventory.Item.Drive",
- "xyz.openbmc_project.Inventory.Item.StorageController"};
+ asyncResp->res.jsonValue["Status"] = {
+ {"Health", "OK"},
+ {"State", "Enabled"},
+ };
+ constexpr const std::array<const char*, 4> inventoryForSystems = {
+ "xyz.openbmc_project.Inventory.Item.Dimm",
+ "xyz.openbmc_project.Inventory.Item.Cpu",
+ "xyz.openbmc_project.Inventory.Item.Drive",
+ "xyz.openbmc_project.Inventory.Item.StorageController"};
- auto health = std::make_shared<HealthPopulate>(asyncResp);
- crow::connections::systemBus->async_method_call(
- [health](const boost::system::error_code ec,
- std::vector<std::string>& resp) {
- if (ec)
+ auto health = std::make_shared<HealthPopulate>(asyncResp);
+ crow::connections::systemBus->async_method_call(
+ [health](const boost::system::error_code ec,
+ std::vector<std::string>& resp) {
+ if (ec)
+ {
+ // no inventory
+ return;
+ }
+
+ health->inventory = std::move(resp);
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
+ int32_t(0), inventoryForSystems);
+
+ health->populate();
+
+ getMainChassisId(
+ asyncResp, [](const std::string& chassisId,
+ const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
+ aRsp->res.jsonValue["Links"]["Chassis"] = {
+ {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
+ });
+
+ getLocationIndicatorActive(asyncResp);
+ // TODO (Gunnar): Remove IndicatorLED after enough time has passed
+ getIndicatorLedState(asyncResp);
+ getComputerSystem(asyncResp, health);
+ getHostState(asyncResp);
+ getBootProperties(asyncResp);
+ getBootProgress(asyncResp);
+ getPCIeDeviceList(asyncResp, "PCIeDevices");
+ getHostWatchdogTimer(asyncResp);
+ getPowerRestorePolicy(asyncResp);
+ getAutomaticRetry(asyncResp);
+ getLastResetTime(asyncResp);
+#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
+ getProvisioningStatus(asyncResp);
+#endif
+ });
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
+ .privileges({"ConfigureComponent"})
+ .methods(boost::beast::http::verb::patch)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ std::optional<bool> locationIndicatorActive;
+ std::optional<std::string> indicatorLed;
+ std::optional<nlohmann::json> bootProps;
+ std::optional<nlohmann::json> wdtTimerProps;
+ std::optional<std::string> assetTag;
+ std::optional<std::string> powerRestorePolicy;
+
+ if (!json_util::readJson(
+ req, asyncResp->res, "IndicatorLED", indicatorLed,
+ "LocationIndicatorActive", locationIndicatorActive,
+ "Boot", bootProps, "WatchdogTimer", wdtTimerProps,
+ "PowerRestorePolicy", powerRestorePolicy, "AssetTag",
+ assetTag))
{
- // no inventory
return;
}
- health->inventory = std::move(resp);
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
- int32_t(0), inventoryForSystems);
+ asyncResp->res.result(boost::beast::http::status::no_content);
- health->populate();
+ if (assetTag)
+ {
+ setAssetTag(asyncResp, *assetTag);
+ }
- getMainChassisId(
- asyncResp, [](const std::string& chassisId,
- const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
- aRsp->res.jsonValue["Links"]["Chassis"] = {
- {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
+ if (wdtTimerProps)
+ {
+ std::optional<bool> wdtEnable;
+ std::optional<std::string> wdtTimeOutAction;
+
+ if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
+ "FunctionEnabled", wdtEnable,
+ "TimeoutAction", wdtTimeOutAction))
+ {
+ return;
+ }
+ setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
+ }
+
+ if (bootProps)
+ {
+ std::optional<std::string> bootSource;
+ std::optional<std::string> bootEnable;
+ std::optional<std::string> automaticRetryConfig;
+
+ if (!json_util::readJson(
+ *bootProps, asyncResp->res,
+ "BootSourceOverrideTarget", bootSource,
+ "BootSourceOverrideEnabled", bootEnable,
+ "AutomaticRetryConfig", automaticRetryConfig))
+ {
+ return;
+ }
+ if (bootSource || bootEnable)
+ {
+ setBootSourceProperties(asyncResp,
+ std::move(bootSource),
+ std::move(bootEnable));
+ }
+ if (automaticRetryConfig)
+ {
+ setAutomaticRetry(asyncResp, *automaticRetryConfig);
+ }
+ }
+
+ if (locationIndicatorActive)
+ {
+ setLocationIndicatorActive(asyncResp,
+ *locationIndicatorActive);
+ }
+
+ // TODO (Gunnar): Remove IndicatorLED after enough time has
+ // passed
+ if (indicatorLed)
+ {
+ setIndicatorLedState(asyncResp, *indicatorLed);
+ asyncResp->res.addHeader(
+ boost::beast::http::field::warning,
+ "299 - \"IndicatorLED is deprecated. Use "
+ "LocationIndicatorActive instead.\"");
+ }
+
+ if (powerRestorePolicy)
+ {
+ setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
+ }
});
-
- getLocationIndicatorActive(asyncResp);
- // TODO (Gunnar): Remove IndicatorLED after enough time has passed
- getIndicatorLedState(asyncResp);
- getComputerSystem(asyncResp, health);
- getHostState(asyncResp);
- getBootProperties(asyncResp);
- getBootProgress(asyncResp);
- getPCIeDeviceList(asyncResp, "PCIeDevices");
- getHostWatchdogTimer(asyncResp);
- getPowerRestorePolicy(asyncResp);
- getAutomaticRetry(asyncResp);
- getLastResetTime(asyncResp);
-#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
- getProvisioningStatus(asyncResp);
-#endif
- }
-
- void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- std::optional<bool> locationIndicatorActive;
- std::optional<std::string> indicatorLed;
- std::optional<nlohmann::json> bootProps;
- std::optional<nlohmann::json> wdtTimerProps;
- std::optional<std::string> assetTag;
- std::optional<std::string> powerRestorePolicy;
-
- if (!json_util::readJson(
- req, asyncResp->res, "IndicatorLED", indicatorLed,
- "LocationIndicatorActive", locationIndicatorActive, "Boot",
- bootProps, "WatchdogTimer", wdtTimerProps, "PowerRestorePolicy",
- powerRestorePolicy, "AssetTag", assetTag))
- {
- return;
- }
-
- asyncResp->res.result(boost::beast::http::status::no_content);
-
- if (assetTag)
- {
- setAssetTag(asyncResp, *assetTag);
- }
-
- if (wdtTimerProps)
- {
- std::optional<bool> wdtEnable;
- std::optional<std::string> wdtTimeOutAction;
-
- if (!json_util::readJson(*wdtTimerProps, asyncResp->res,
- "FunctionEnabled", wdtEnable,
- "TimeoutAction", wdtTimeOutAction))
- {
- return;
- }
- setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
- }
-
- if (bootProps)
- {
- std::optional<std::string> bootSource;
- std::optional<std::string> bootEnable;
- std::optional<std::string> automaticRetryConfig;
-
- if (!json_util::readJson(
- *bootProps, asyncResp->res, "BootSourceOverrideTarget",
- bootSource, "BootSourceOverrideEnabled", bootEnable,
- "AutomaticRetryConfig", automaticRetryConfig))
- {
- return;
- }
- if (bootSource || bootEnable)
- {
- setBootSourceProperties(asyncResp, std::move(bootSource),
- std::move(bootEnable));
- }
- if (automaticRetryConfig)
- {
- setAutomaticRetry(asyncResp, *automaticRetryConfig);
- }
- }
-
- if (locationIndicatorActive)
- {
- setLocationIndicatorActive(asyncResp, *locationIndicatorActive);
- }
-
- // TODO (Gunnar): Remove IndicatorLED after enough time has passed
- if (indicatorLed)
- {
- setIndicatorLedState(asyncResp, *indicatorLed);
- asyncResp->res.addHeader(boost::beast::http::field::warning,
- "299 - \"IndicatorLED is deprecated. Use "
- "LocationIndicatorActive instead.\"");
- }
-
- if (powerRestorePolicy)
- {
- setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
- }
- }
-};
+}
/**
* SystemResetActionInfo derived class for delivering Computer Systems
* ResetType AllowableValues using ResetInfo schema.
*/
-class SystemResetActionInfo : public Node
+inline void requestRoutesSystemResetActionInfo(App& app)
{
- public:
- /*
- * Default Constructor
- */
- SystemResetActionInfo(App& app) :
- Node(app, "/redfish/v1/Systems/system/ResetActionInfo/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
- private:
/**
* Functions triggers appropriate requests on DBus
*/
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue = {
- {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
- {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
- {"Name", "Reset Action Info"},
- {"Id", "ResetActionInfo"},
- {"Parameters",
- {{{"Name", "ResetType"},
- {"Required", true},
- {"DataType", "String"},
- {"AllowableValues",
- {"On", "ForceOff", "ForceOn", "ForceRestart", "GracefulRestart",
- "GracefulShutdown", "PowerCycle", "Nmi"}}}}}};
- }
-};
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue = {
+ {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
+ {"@odata.id", "/redfish/v1/Systems/system/ResetActionInfo"},
+ {"Name", "Reset Action Info"},
+ {"Id", "ResetActionInfo"},
+ {"Parameters",
+ {{{"Name", "ResetType"},
+ {"Required", true},
+ {"DataType", "String"},
+ {"AllowableValues",
+ {"On", "ForceOff", "ForceOn", "ForceRestart",
+ "GracefulRestart", "GracefulShutdown", "PowerCycle",
+ "Nmi"}}}}}};
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/task.hpp b/redfish-core/lib/task.hpp
index 275806f..308a699 100644
--- a/redfish-core/lib/task.hpp
+++ b/redfish-core/lib/task.hpp
@@ -15,8 +15,7 @@
*/
#pragma once
-#include "node.hpp"
-
+#include <app.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/container/flat_map.hpp>
@@ -314,223 +313,171 @@
} // namespace task
-class TaskMonitor : public Node
+inline void requestRoutesTaskMonitor(App& app)
{
- public:
- TaskMonitor(App& app) :
- Node((app), "/redfish/v1/TaskService/Tasks/<str>/Monitor/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/TaskService/Tasks/<str>/Monitor/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& strParam) {
+ auto find = std::find_if(
+ task::tasks.begin(), task::tasks.end(),
+ [&strParam](const std::shared_ptr<task::TaskData>& task) {
+ if (!task)
+ {
+ return false;
+ }
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
+ // we compare against the string version as on failure
+ // strtoul returns 0
+ return std::to_string(task->index) == strParam;
+ });
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- const std::string& strParam = params[0];
- auto find = std::find_if(
- task::tasks.begin(), task::tasks.end(),
- [&strParam](const std::shared_ptr<task::TaskData>& task) {
- if (!task)
+ if (find == task::tasks.end())
{
- return false;
+ messages::resourceNotFound(asyncResp->res, "Monitor",
+ strParam);
+ return;
+ }
+ std::shared_ptr<task::TaskData>& ptr = *find;
+ // monitor expires after 204
+ if (ptr->gave204)
+ {
+ messages::resourceNotFound(asyncResp->res, "Monitor",
+ strParam);
+ return;
+ }
+ ptr->populateResp(asyncResp->res);
+ });
+}
+
+inline void requestRoutesTask(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/TaskService/Tasks/<str>/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& strParam) {
+ auto find = std::find_if(
+ task::tasks.begin(), task::tasks.end(),
+ [&strParam](const std::shared_ptr<task::TaskData>& task) {
+ if (!task)
+ {
+ return false;
+ }
+
+ // we compare against the string version as on failure
+ // strtoul returns 0
+ return std::to_string(task->index) == strParam;
+ });
+
+ if (find == task::tasks.end())
+ {
+ messages::resourceNotFound(asyncResp->res, "Tasks",
+ strParam);
+ return;
}
- // we compare against the string version as on failure strtoul
- // returns 0
- return std::to_string(task->index) == strParam;
- });
+ std::shared_ptr<task::TaskData>& ptr = *find;
- if (find == task::tasks.end())
- {
- messages::resourceNotFound(asyncResp->res, "Monitor", strParam);
- return;
- }
- std::shared_ptr<task::TaskData>& ptr = *find;
- // monitor expires after 204
- if (ptr->gave204)
- {
- messages::resourceNotFound(asyncResp->res, "Monitor", strParam);
- return;
- }
- ptr->populateResp(asyncResp->res);
- }
-};
-
-class Task : public Node
-{
- public:
- Task(App& app) :
- Node((app), "/redfish/v1/TaskService/Tasks/<str>/", std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
-
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- const std::string& strParam = params[0];
- auto find = std::find_if(
- task::tasks.begin(), task::tasks.end(),
- [&strParam](const std::shared_ptr<task::TaskData>& task) {
- if (!task)
+ asyncResp->res.jsonValue["@odata.type"] = "#Task.v1_4_3.Task";
+ asyncResp->res.jsonValue["Id"] = strParam;
+ asyncResp->res.jsonValue["Name"] = "Task " + strParam;
+ asyncResp->res.jsonValue["TaskState"] = ptr->state;
+ asyncResp->res.jsonValue["StartTime"] =
+ crow::utility::getDateTime(ptr->startTime);
+ if (ptr->endTime)
{
- return false;
+ asyncResp->res.jsonValue["EndTime"] =
+ crow::utility::getDateTime(*(ptr->endTime));
}
-
- // we compare against the string version as on failure strtoul
- // returns 0
- return std::to_string(task->index) == strParam;
+ asyncResp->res.jsonValue["TaskStatus"] = ptr->status;
+ asyncResp->res.jsonValue["Messages"] = ptr->messages;
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/TaskService/Tasks/" + strParam;
+ if (!ptr->gave204)
+ {
+ asyncResp->res.jsonValue["TaskMonitor"] =
+ "/redfish/v1/TaskService/Tasks/" + strParam +
+ "/Monitor";
+ }
+ if (ptr->payload)
+ {
+ const task::Payload& p = *(ptr->payload);
+ asyncResp->res.jsonValue["Payload"] = {
+ {"TargetUri", p.targetUri},
+ {"HttpOperation", p.httpOperation},
+ {"HttpHeaders", p.httpHeaders},
+ {"JsonBody",
+ p.jsonBody.dump(
+ 2, ' ', true,
+ nlohmann::json::error_handler_t::replace)}};
+ }
+ asyncResp->res.jsonValue["PercentComplete"] =
+ ptr->percentComplete;
});
+}
- if (find == task::tasks.end())
- {
- messages::resourceNotFound(asyncResp->res, "Tasks", strParam);
- return;
- }
-
- std::shared_ptr<task::TaskData>& ptr = *find;
-
- asyncResp->res.jsonValue["@odata.type"] = "#Task.v1_4_3.Task";
- asyncResp->res.jsonValue["Id"] = strParam;
- asyncResp->res.jsonValue["Name"] = "Task " + strParam;
- asyncResp->res.jsonValue["TaskState"] = ptr->state;
- asyncResp->res.jsonValue["StartTime"] =
- crow::utility::getDateTime(ptr->startTime);
- if (ptr->endTime)
- {
- asyncResp->res.jsonValue["EndTime"] =
- crow::utility::getDateTime(*(ptr->endTime));
- }
- asyncResp->res.jsonValue["TaskStatus"] = ptr->status;
- asyncResp->res.jsonValue["Messages"] = ptr->messages;
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/TaskService/Tasks/" + strParam;
- if (!ptr->gave204)
- {
- asyncResp->res.jsonValue["TaskMonitor"] =
- "/redfish/v1/TaskService/Tasks/" + strParam + "/Monitor";
- }
- if (ptr->payload)
- {
- const task::Payload& p = *(ptr->payload);
- asyncResp->res.jsonValue["Payload"] = {
- {"TargetUri", p.targetUri},
- {"HttpOperation", p.httpOperation},
- {"HttpHeaders", p.httpHeaders},
- {"JsonBody",
- p.jsonBody.dump(2, ' ', true,
- nlohmann::json::error_handler_t::replace)}};
- }
- asyncResp->res.jsonValue["PercentComplete"] = ptr->percentComplete;
- }
-};
-
-class TaskCollection : public Node
+inline void requestRoutesTaskCollection(App& app)
{
- public:
- TaskCollection(App& app) : Node(app, "/redfish/v1/TaskService/Tasks/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/TaskService/Tasks/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#TaskCollection.TaskCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/TaskService/Tasks";
+ asyncResp->res.jsonValue["Name"] = "Task Collection";
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ task::tasks.size();
+ nlohmann::json& members = asyncResp->res.jsonValue["Members"];
+ members = nlohmann::json::array();
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
+ for (const std::shared_ptr<task::TaskData>& task : task::tasks)
+ {
+ if (task == nullptr)
+ {
+ continue; // shouldn't be possible
+ }
+ members.emplace_back(nlohmann::json{
+ {"@odata.id", "/redfish/v1/TaskService/Tasks/" +
+ std::to_string(task->index)}});
+ }
+ });
+}
- asyncResp->res.jsonValue["@odata.type"] =
- "#TaskCollection.TaskCollection";
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/TaskService/Tasks";
- asyncResp->res.jsonValue["Name"] = "Task Collection";
- asyncResp->res.jsonValue["Members@odata.count"] = task::tasks.size();
- nlohmann::json& members = asyncResp->res.jsonValue["Members"];
- members = nlohmann::json::array();
-
- for (const std::shared_ptr<task::TaskData>& task : task::tasks)
- {
- if (task == nullptr)
- {
- continue; // shouldn't be possible
- }
- members.emplace_back(
- nlohmann::json{{"@odata.id", "/redfish/v1/TaskService/Tasks/" +
- std::to_string(task->index)}});
- }
- }
-};
-
-class TaskService : public Node
+inline void requestRoutesTaskService(App& app)
{
- public:
- TaskService(App& app) : Node(app, "/redfish/v1/TaskService/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/TaskService/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#TaskService.v1_1_4.TaskService";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/TaskService";
+ asyncResp->res.jsonValue["Name"] = "Task Service";
+ asyncResp->res.jsonValue["Id"] = "TaskService";
+ asyncResp->res.jsonValue["DateTime"] =
+ crow::utility::dateTimeNow();
+ asyncResp->res.jsonValue["CompletedTaskOverWritePolicy"] =
+ "Oldest";
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.type"] =
- "#TaskService.v1_1_4.TaskService";
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/TaskService";
- asyncResp->res.jsonValue["Name"] = "Task Service";
- asyncResp->res.jsonValue["Id"] = "TaskService";
- asyncResp->res.jsonValue["DateTime"] = crow::utility::dateTimeNow();
- asyncResp->res.jsonValue["CompletedTaskOverWritePolicy"] = "Oldest";
+ asyncResp->res.jsonValue["LifeCycleEventOnTaskStateChange"] =
+ true;
- asyncResp->res.jsonValue["LifeCycleEventOnTaskStateChange"] = true;
-
- auto health = std::make_shared<HealthPopulate>(asyncResp);
- health->populate();
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
- asyncResp->res.jsonValue["ServiceEnabled"] = true;
- asyncResp->res.jsonValue["Tasks"] = {
- {"@odata.id", "/redfish/v1/TaskService/Tasks"}};
- }
-};
+ auto health = std::make_shared<HealthPopulate>(asyncResp);
+ health->populate();
+ asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+ asyncResp->res.jsonValue["ServiceEnabled"] = true;
+ asyncResp->res.jsonValue["Tasks"] = {
+ {"@odata.id", "/redfish/v1/TaskService/Tasks"}};
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp
index 9ec0737..e6f5b0f 100644
--- a/redfish-core/lib/telemetry_service.hpp
+++ b/redfish-core/lib/telemetry_service.hpp
@@ -1,90 +1,82 @@
#pragma once
-#include "node.hpp"
#include "utils/telemetry_utils.hpp"
+#include <app.hpp>
+
#include <variant>
namespace redfish
{
-class TelemetryService : public Node
+inline void requestRoutesTelemetryService(App& app)
{
- public:
- TelemetryService(App& app) : Node(app, "/redfish/v1/TelemetryService/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::
+ get)([](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#TelemetryService.v1_2_1.TelemetryService";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/TelemetryService";
+ asyncResp->res.jsonValue["Id"] = "TelemetryService";
+ asyncResp->res.jsonValue["Name"] = "Telemetry Service";
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.type"] =
- "#TelemetryService.v1_2_1.TelemetryService";
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/TelemetryService";
- asyncResp->res.jsonValue["Id"] = "TelemetryService";
- asyncResp->res.jsonValue["Name"] = "Telemetry Service";
+ asyncResp->res.jsonValue["MetricReportDefinitions"]["@odata.id"] =
+ "/redfish/v1/TelemetryService/MetricReportDefinitions";
+ asyncResp->res.jsonValue["MetricReports"]["@odata.id"] =
+ "/redfish/v1/TelemetryService/MetricReports";
- asyncResp->res.jsonValue["MetricReportDefinitions"]["@odata.id"] =
- "/redfish/v1/TelemetryService/MetricReportDefinitions";
- asyncResp->res.jsonValue["MetricReports"]["@odata.id"] =
- "/redfish/v1/TelemetryService/MetricReports";
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](
- const boost::system::error_code ec,
- const std::vector<std::pair<
- std::string, std::variant<uint32_t, uint64_t>>>& ret) {
- if (ec == boost::system::errc::host_unreachable)
- {
- asyncResp->res.jsonValue["Status"]["State"] = "Absent";
- return;
- }
- if (ec)
- {
- BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
-
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
-
- const size_t* maxReports = nullptr;
- const uint64_t* minInterval = nullptr;
- for (const auto& [key, var] : ret)
- {
- if (key == "MaxReports")
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](
+ const boost::system::error_code ec,
+ const std::vector<std::pair<
+ std::string, std::variant<uint32_t, uint64_t>>>& ret) {
+ if (ec == boost::system::errc::host_unreachable)
{
- maxReports = std::get_if<size_t>(&var);
+ asyncResp->res.jsonValue["Status"]["State"] = "Absent";
+ return;
}
- else if (key == "MinInterval")
+ if (ec)
{
- minInterval = std::get_if<uint64_t>(&var);
+ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
+ messages::internalError(asyncResp->res);
+ return;
}
- }
- if (!maxReports || !minInterval)
- {
- BMCWEB_LOG_ERROR
- << "Property type mismatch or property is missing";
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue["MaxReports"] = *maxReports;
- asyncResp->res.jsonValue["MinCollectionInterval"] =
- time_utils::toDurationString(std::chrono::milliseconds(
- static_cast<time_t>(*minInterval)));
- },
- telemetry::service, "/xyz/openbmc_project/Telemetry/Reports",
- "org.freedesktop.DBus.Properties", "GetAll",
- "xyz.openbmc_project.Telemetry.ReportManager");
- }
-};
+ asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+
+ const size_t* maxReports = nullptr;
+ const uint64_t* minInterval = nullptr;
+ for (const auto& [key, var] : ret)
+ {
+ if (key == "MaxReports")
+ {
+ maxReports = std::get_if<size_t>(&var);
+ }
+ else if (key == "MinInterval")
+ {
+ minInterval = std::get_if<uint64_t>(&var);
+ }
+ }
+ if (!maxReports || !minInterval)
+ {
+ BMCWEB_LOG_ERROR
+ << "Property type mismatch or property is missing";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ asyncResp->res.jsonValue["MaxReports"] = *maxReports;
+ asyncResp->res.jsonValue["MinCollectionInterval"] =
+ time_utils::toDurationString(std::chrono::milliseconds(
+ static_cast<time_t>(*minInterval)));
+ },
+ telemetry::service, "/xyz/openbmc_project/Telemetry/Reports",
+ "org.freedesktop.DBus.Properties", "GetAll",
+ "xyz.openbmc_project.Telemetry.ReportManager");
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/thermal.hpp b/redfish-core/lib/thermal.hpp
index e064f1f..078da9c 100644
--- a/redfish-core/lib/thermal.hpp
+++ b/redfish-core/lib/thermal.hpp
@@ -15,106 +15,85 @@
*/
#pragma once
-#include "node.hpp"
#include "sensors.hpp"
+#include <app.hpp>
+
namespace redfish
{
-class Thermal : public Node
+inline void requestRoutesThermal(App& app)
{
- public:
- Thermal(App& app) :
- Node((app), "/redfish/v1/Chassis/<str>/Thermal/", std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Thermal/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisName) {
+ auto thermalPaths =
+ sensors::dbus::paths.find(sensors::node::thermal);
+ if (thermalPaths == sensors::dbus::paths.end())
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
+ auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
+ asyncResp, chassisName, thermalPaths->second,
+ sensors::node::thermal);
- return;
- }
+ // TODO Need to get Chassis Redundancy information.
+ getChassisData(sensorAsyncResp);
+ });
- auto thermalPaths = sensors::dbus::paths.find(sensors::node::thermal);
- if (thermalPaths == sensors::dbus::paths.end())
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Thermal/")
+ .privileges({"ConfigureManager"})
+ .methods(boost::beast::http::verb::patch)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisName) {
+ auto thermalPaths =
+ sensors::dbus::paths.find(sensors::node::thermal);
+ if (thermalPaths == sensors::dbus::paths.end())
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- const std::string& chassisName = params[0];
- auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
- asyncResp, chassisName, thermalPaths->second,
- sensors::node::thermal);
+ std::optional<std::vector<nlohmann::json>>
+ temperatureCollections;
+ std::optional<std::vector<nlohmann::json>> fanCollections;
+ std::unordered_map<std::string, std::vector<nlohmann::json>>
+ allCollections;
- // TODO Need to get Chassis Redundancy information.
- getChassisData(sensorAsyncResp);
- }
- void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 1)
- {
+ auto sensorsAsyncResp = std::make_shared<SensorsAsyncResp>(
+ asyncResp, chassisName, thermalPaths->second,
+ sensors::node::thermal);
- messages::internalError(asyncResp->res);
- return;
- }
-
- auto thermalPaths = sensors::dbus::paths.find(sensors::node::thermal);
- if (thermalPaths == sensors::dbus::paths.end())
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- const std::string& chassisName = params[0];
- std::optional<std::vector<nlohmann::json>> temperatureCollections;
- std::optional<std::vector<nlohmann::json>> fanCollections;
- std::unordered_map<std::string, std::vector<nlohmann::json>>
- allCollections;
-
- auto sensorsAsyncResp = std::make_shared<SensorsAsyncResp>(
- asyncResp, chassisName, thermalPaths->second,
- sensors::node::thermal);
-
- if (!json_util::readJson(req, sensorsAsyncResp->asyncResp->res,
- "Temperatures", temperatureCollections, "Fans",
- fanCollections))
- {
- return;
- }
- if (!temperatureCollections && !fanCollections)
- {
- messages::resourceNotFound(sensorsAsyncResp->asyncResp->res,
- "Thermal", "Temperatures / Voltages");
- return;
- }
- if (temperatureCollections)
- {
- allCollections.emplace("Temperatures",
- *std::move(temperatureCollections));
- }
- if (fanCollections)
- {
- allCollections.emplace("Fans", *std::move(fanCollections));
- }
-
- checkAndDoSensorsOverride(sensorsAsyncResp, allCollections);
- }
-};
+ if (!json_util::readJson(req, sensorsAsyncResp->asyncResp->res,
+ "Temperatures", temperatureCollections,
+ "Fans", fanCollections))
+ {
+ return;
+ }
+ if (!temperatureCollections && !fanCollections)
+ {
+ messages::resourceNotFound(sensorsAsyncResp->asyncResp->res,
+ "Thermal",
+ "Temperatures / Voltages");
+ return;
+ }
+ if (temperatureCollections)
+ {
+ allCollections.emplace("Temperatures",
+ *std::move(temperatureCollections));
+ }
+ if (fanCollections)
+ {
+ allCollections.emplace("Fans", *std::move(fanCollections));
+ }
+ checkAndDoSensorsOverride(sensorsAsyncResp, allCollections);
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
index 9f6c6f9..bfab6fb 100644
--- a/redfish-core/lib/update_service.hpp
+++ b/redfish-core/lib/update_service.hpp
@@ -15,8 +15,7 @@
*/
#pragma once
-#include "node.hpp"
-
+#include <app.hpp>
#include <boost/container/flat_map.hpp>
#include <utils/fw_utils.hpp>
@@ -33,14 +32,14 @@
// Timer for software available
static std::unique_ptr<boost::asio::steady_timer> fwAvailableTimer;
-static void cleanUp()
+inline static void cleanUp()
{
fwUpdateInProgress = false;
fwUpdateMatcher = nullptr;
fwUpdateErrorMatcher = nullptr;
}
-static void activateImage(const std::string& objPath,
- const std::string& service)
+inline static void activateImage(const std::string& objPath,
+ const std::string& service)
{
BMCWEB_LOG_DEBUG << "Activate image for " << objPath << " " << service;
crow::connections::systemBus->async_method_call(
@@ -383,589 +382,555 @@
* UpdateServiceActionsSimpleUpdate class supports handle POST method for
* SimpleUpdate action.
*/
-class UpdateServiceActionsSimpleUpdate : public Node
+inline void requestRoutesUpdateServiceActionsSimpleUpdate(App& app)
{
- public:
- UpdateServiceActionsSimpleUpdate(App& app) :
- Node(app,
- "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate/")
+ .privileges({"ConfigureComponents"})
+ .methods(
+ boost::beast::http::verb::
+ post)([](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ std::optional<std::string> transferProtocol;
+ std::string imageURI;
- private:
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- std::optional<std::string> transferProtocol;
- std::string imageURI;
+ BMCWEB_LOG_DEBUG << "Enter UpdateService.SimpleUpdate doPost";
- BMCWEB_LOG_DEBUG << "Enter UpdateService.SimpleUpdate doPost";
+ // User can pass in both TransferProtocol and ImageURI parameters or
+ // they can pass in just the ImageURI with the transfer protocol
+ // embedded within it.
+ // 1) TransferProtocol:TFTP ImageURI:1.1.1.1/myfile.bin
+ // 2) ImageURI:tftp://1.1.1.1/myfile.bin
- // User can pass in both TransferProtocol and ImageURI parameters or
- // they can pass in just the ImageURI with the transfer protocol
- // embedded within it.
- // 1) TransferProtocol:TFTP ImageURI:1.1.1.1/myfile.bin
- // 2) ImageURI:tftp://1.1.1.1/myfile.bin
+ if (!json_util::readJson(req, asyncResp->res, "TransferProtocol",
+ transferProtocol, "ImageURI", imageURI))
+ {
+ BMCWEB_LOG_DEBUG
+ << "Missing TransferProtocol or ImageURI parameter";
+ return;
+ }
+ if (!transferProtocol)
+ {
+ // Must be option 2
+ // Verify ImageURI has transfer protocol in it
+ size_t separator = imageURI.find(':');
+ if ((separator == std::string::npos) ||
+ ((separator + 1) > imageURI.size()))
+ {
+ messages::actionParameterValueTypeError(
+ asyncResp->res, imageURI, "ImageURI",
+ "UpdateService.SimpleUpdate");
+ BMCWEB_LOG_ERROR << "ImageURI missing transfer protocol: "
+ << imageURI;
+ return;
+ }
+ transferProtocol = imageURI.substr(0, separator);
+ // Ensure protocol is upper case for a common comparison path
+ // below
+ boost::to_upper(*transferProtocol);
+ BMCWEB_LOG_DEBUG << "Encoded transfer protocol "
+ << *transferProtocol;
- if (!json_util::readJson(req, asyncResp->res, "TransferProtocol",
- transferProtocol, "ImageURI", imageURI))
- {
- BMCWEB_LOG_DEBUG
- << "Missing TransferProtocol or ImageURI parameter";
- return;
- }
- if (!transferProtocol)
- {
- // Must be option 2
- // Verify ImageURI has transfer protocol in it
- size_t separator = imageURI.find(':');
+ // Adjust imageURI to not have the protocol on it for parsing
+ // below
+ // ex. tftp://1.1.1.1/myfile.bin -> 1.1.1.1/myfile.bin
+ imageURI = imageURI.substr(separator + 3);
+ BMCWEB_LOG_DEBUG << "Adjusted imageUri " << imageURI;
+ }
+
+ // OpenBMC currently only supports TFTP
+ if (*transferProtocol != "TFTP")
+ {
+ messages::actionParameterNotSupported(
+ asyncResp->res, "TransferProtocol",
+ "UpdateService.SimpleUpdate");
+ BMCWEB_LOG_ERROR << "Request incorrect protocol parameter: "
+ << *transferProtocol;
+ return;
+ }
+
+ // Format should be <IP or Hostname>/<file> for imageURI
+ size_t separator = imageURI.find('/');
if ((separator == std::string::npos) ||
((separator + 1) > imageURI.size()))
{
messages::actionParameterValueTypeError(
asyncResp->res, imageURI, "ImageURI",
"UpdateService.SimpleUpdate");
- BMCWEB_LOG_ERROR << "ImageURI missing transfer protocol: "
- << imageURI;
- return;
- }
- transferProtocol = imageURI.substr(0, separator);
- // Ensure protocol is upper case for a common comparison path below
- boost::to_upper(*transferProtocol);
- BMCWEB_LOG_DEBUG << "Encoded transfer protocol "
- << *transferProtocol;
-
- // Adjust imageURI to not have the protocol on it for parsing
- // below
- // ex. tftp://1.1.1.1/myfile.bin -> 1.1.1.1/myfile.bin
- imageURI = imageURI.substr(separator + 3);
- BMCWEB_LOG_DEBUG << "Adjusted imageUri " << imageURI;
- }
-
- // OpenBMC currently only supports TFTP
- if (*transferProtocol != "TFTP")
- {
- messages::actionParameterNotSupported(asyncResp->res,
- "TransferProtocol",
- "UpdateService.SimpleUpdate");
- BMCWEB_LOG_ERROR << "Request incorrect protocol parameter: "
- << *transferProtocol;
- return;
- }
-
- // Format should be <IP or Hostname>/<file> for imageURI
- size_t separator = imageURI.find('/');
- if ((separator == std::string::npos) ||
- ((separator + 1) > imageURI.size()))
- {
- messages::actionParameterValueTypeError(
- asyncResp->res, imageURI, "ImageURI",
- "UpdateService.SimpleUpdate");
- BMCWEB_LOG_ERROR << "Invalid ImageURI: " << imageURI;
- return;
- }
-
- std::string tftpServer = imageURI.substr(0, separator);
- std::string fwFile = imageURI.substr(separator + 1);
- BMCWEB_LOG_DEBUG << "Server: " << tftpServer + " File: " << fwFile;
-
- // Setup callback for when new software detected
- // Give TFTP 10 minutes to complete
- monitorForSoftwareAvailable(
- asyncResp, req,
- "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate",
- 600);
-
- // TFTP can take up to 10 minutes depending on image size and
- // connection speed. Return to caller as soon as the TFTP operation
- // has been started. The callback above will ensure the activate
- // is started once the download has completed
- redfish::messages::success(asyncResp->res);
-
- // Call TFTP service
- crow::connections::systemBus->async_method_call(
- [](const boost::system::error_code ec) {
- if (ec)
- {
- // messages::internalError(asyncResp->res);
- cleanUp();
- BMCWEB_LOG_DEBUG << "error_code = " << ec;
- BMCWEB_LOG_DEBUG << "error msg = " << ec.message();
- }
- else
- {
- BMCWEB_LOG_DEBUG << "Call to DownloaViaTFTP Success";
- }
- },
- "xyz.openbmc_project.Software.Download",
- "/xyz/openbmc_project/software", "xyz.openbmc_project.Common.TFTP",
- "DownloadViaTFTP", fwFile, tftpServer);
-
- BMCWEB_LOG_DEBUG << "Exit UpdateService.SimpleUpdate doPost";
- }
-};
-
-class UpdateService : public Node
-{
- public:
- UpdateService(App& app) : Node(app, "/redfish/v1/UpdateService/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.type"] =
- "#UpdateService.v1_4_0.UpdateService";
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/UpdateService";
- asyncResp->res.jsonValue["Id"] = "UpdateService";
- asyncResp->res.jsonValue["Description"] = "Service for Software Update";
- asyncResp->res.jsonValue["Name"] = "Update Service";
- asyncResp->res.jsonValue["HttpPushUri"] = "/redfish/v1/UpdateService";
- // UpdateService cannot be disabled
- asyncResp->res.jsonValue["ServiceEnabled"] = true;
- asyncResp->res.jsonValue["FirmwareInventory"] = {
- {"@odata.id", "/redfish/v1/UpdateService/FirmwareInventory"}};
-#ifdef BMCWEB_INSECURE_ENABLE_REDFISH_FW_TFTP_UPDATE
- // Update Actions object.
- nlohmann::json& updateSvcSimpleUpdate =
- asyncResp->res.jsonValue["Actions"]["#UpdateService.SimpleUpdate"];
- updateSvcSimpleUpdate["target"] =
- "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate";
- updateSvcSimpleUpdate["TransferProtocol@Redfish.AllowableValues"] = {
- "TFTP"};
-#endif
- // Get the current ApplyTime value
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
- const std::variant<std::string>& applyTime) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
- messages::internalError(asyncResp->res);
- return;
- }
-
- const std::string* s = std::get_if<std::string>(&applyTime);
- if (s == nullptr)
- {
- return;
- }
- // Store the ApplyTime Value
- if (*s == "xyz.openbmc_project.Software.ApplyTime."
- "RequestedApplyTimes.Immediate")
- {
- asyncResp->res
- .jsonValue["HttpPushUriOptions"]["HttpPushUriApplyTime"]
- ["ApplyTime"] = "Immediate";
- }
- else if (*s == "xyz.openbmc_project.Software.ApplyTime."
- "RequestedApplyTimes.OnReset")
- {
- asyncResp->res
- .jsonValue["HttpPushUriOptions"]["HttpPushUriApplyTime"]
- ["ApplyTime"] = "OnReset";
- }
- },
- "xyz.openbmc_project.Settings",
- "/xyz/openbmc_project/software/apply_time",
- "org.freedesktop.DBus.Properties", "Get",
- "xyz.openbmc_project.Software.ApplyTime", "RequestedApplyTime");
- }
-
- void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- BMCWEB_LOG_DEBUG << "doPatch...";
-
- std::optional<nlohmann::json> pushUriOptions;
- if (!json_util::readJson(req, asyncResp->res, "HttpPushUriOptions",
- pushUriOptions))
- {
- return;
- }
-
- if (pushUriOptions)
- {
- std::optional<nlohmann::json> pushUriApplyTime;
- if (!json_util::readJson(*pushUriOptions, asyncResp->res,
- "HttpPushUriApplyTime", pushUriApplyTime))
- {
+ BMCWEB_LOG_ERROR << "Invalid ImageURI: " << imageURI;
return;
}
- if (pushUriApplyTime)
- {
- std::optional<std::string> applyTime;
- if (!json_util::readJson(*pushUriApplyTime, asyncResp->res,
- "ApplyTime", applyTime))
- {
- return;
- }
+ std::string tftpServer = imageURI.substr(0, separator);
+ std::string fwFile = imageURI.substr(separator + 1);
+ BMCWEB_LOG_DEBUG << "Server: " << tftpServer + " File: " << fwFile;
- if (applyTime)
- {
- std::string applyTimeNewVal;
- if (applyTime == "Immediate")
+ // Setup callback for when new software detected
+ // Give TFTP 10 minutes to complete
+ monitorForSoftwareAvailable(
+ asyncResp, req,
+ "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate",
+ 600);
+
+ // TFTP can take up to 10 minutes depending on image size and
+ // connection speed. Return to caller as soon as the TFTP operation
+ // has been started. The callback above will ensure the activate
+ // is started once the download has completed
+ redfish::messages::success(asyncResp->res);
+
+ // Call TFTP service
+ crow::connections::systemBus->async_method_call(
+ [](const boost::system::error_code ec) {
+ if (ec)
{
- applyTimeNewVal =
- "xyz.openbmc_project.Software.ApplyTime."
- "RequestedApplyTimes.Immediate";
- }
- else if (applyTime == "OnReset")
- {
- applyTimeNewVal =
- "xyz.openbmc_project.Software.ApplyTime."
- "RequestedApplyTimes.OnReset";
+ // messages::internalError(asyncResp->res);
+ cleanUp();
+ BMCWEB_LOG_DEBUG << "error_code = " << ec;
+ BMCWEB_LOG_DEBUG << "error msg = " << ec.message();
}
else
{
- BMCWEB_LOG_INFO
- << "ApplyTime value is not in the list of "
- "acceptable values";
- messages::propertyValueNotInList(
- asyncResp->res, *applyTime, "ApplyTime");
+ BMCWEB_LOG_DEBUG << "Call to DownloaViaTFTP Success";
+ }
+ },
+ "xyz.openbmc_project.Software.Download",
+ "/xyz/openbmc_project/software",
+ "xyz.openbmc_project.Common.TFTP", "DownloadViaTFTP", fwFile,
+ tftpServer);
+
+ BMCWEB_LOG_DEBUG << "Exit UpdateService.SimpleUpdate doPost";
+ });
+}
+
+inline void requestRoutesUpdateService(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::
+ get)([](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#UpdateService.v1_4_0.UpdateService";
+ asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/UpdateService";
+ asyncResp->res.jsonValue["Id"] = "UpdateService";
+ asyncResp->res.jsonValue["Description"] =
+ "Service for Software Update";
+ asyncResp->res.jsonValue["Name"] = "Update Service";
+ asyncResp->res.jsonValue["HttpPushUri"] =
+ "/redfish/v1/UpdateService";
+ // UpdateService cannot be disabled
+ asyncResp->res.jsonValue["ServiceEnabled"] = true;
+ asyncResp->res.jsonValue["FirmwareInventory"] = {
+ {"@odata.id", "/redfish/v1/UpdateService/FirmwareInventory"}};
+#ifdef BMCWEB_INSECURE_ENABLE_REDFISH_FW_TFTP_UPDATE
+ // Update Actions object.
+ nlohmann::json& updateSvcSimpleUpdate =
+ asyncResp->res
+ .jsonValue["Actions"]["#UpdateService.SimpleUpdate"];
+ updateSvcSimpleUpdate["target"] =
+ "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate";
+ updateSvcSimpleUpdate["TransferProtocol@Redfish.AllowableValues"] =
+ {"TFTP"};
+#endif
+ // Get the current ApplyTime value
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec,
+ const std::variant<std::string>& applyTime) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+ messages::internalError(asyncResp->res);
return;
}
- // Set the requested image apply time value
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "D-Bus responses error: "
- << ec;
- messages::internalError(asyncResp->res);
- return;
- }
- messages::success(asyncResp->res);
- },
- "xyz.openbmc_project.Settings",
- "/xyz/openbmc_project/software/apply_time",
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Software.ApplyTime",
- "RequestedApplyTime",
- std::variant<std::string>{applyTimeNewVal});
- }
- }
- }
- }
+ const std::string* s = std::get_if<std::string>(&applyTime);
+ if (s == nullptr)
+ {
+ return;
+ }
+ // Store the ApplyTime Value
+ if (*s == "xyz.openbmc_project.Software.ApplyTime."
+ "RequestedApplyTimes.Immediate")
+ {
+ asyncResp->res
+ .jsonValue["HttpPushUriOptions"]
+ ["HttpPushUriApplyTime"]["ApplyTime"] =
+ "Immediate";
+ }
+ else if (*s == "xyz.openbmc_project.Software.ApplyTime."
+ "RequestedApplyTimes.OnReset")
+ {
+ asyncResp->res
+ .jsonValue["HttpPushUriOptions"]
+ ["HttpPushUriApplyTime"]["ApplyTime"] =
+ "OnReset";
+ }
+ },
+ "xyz.openbmc_project.Settings",
+ "/xyz/openbmc_project/software/apply_time",
+ "org.freedesktop.DBus.Properties", "Get",
+ "xyz.openbmc_project.Software.ApplyTime", "RequestedApplyTime");
+ });
+ BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::patch)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ BMCWEB_LOG_DEBUG << "doPatch...";
- void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request& req,
- const std::vector<std::string>&) override
- {
- BMCWEB_LOG_DEBUG << "doPost...";
-
- // Setup callback for when new software detected
- monitorForSoftwareAvailable(asyncResp, req,
- "/redfish/v1/UpdateService");
-
- std::string filepath(
- "/tmp/images/" +
- boost::uuids::to_string(boost::uuids::random_generator()()));
- BMCWEB_LOG_DEBUG << "Writing file to " << filepath;
- std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary |
- std::ofstream::trunc);
- out << req.body;
- out.close();
- BMCWEB_LOG_DEBUG << "file upload complete!!";
- }
-};
-
-class SoftwareInventoryCollection : public Node
-{
- public:
- SoftwareInventoryCollection(App& app) :
- Node(app, "/redfish/v1/UpdateService/FirmwareInventory/")
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&, const std::vector<std::string>&) override
- {
- asyncResp->res.jsonValue["@odata.type"] =
- "#SoftwareInventoryCollection.SoftwareInventoryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/UpdateService/FirmwareInventory";
- asyncResp->res.jsonValue["Name"] = "Software Inventory Collection";
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](
- const boost::system::error_code ec,
- const std::vector<std::pair<
- std::string, std::vector<std::pair<
- std::string, std::vector<std::string>>>>>&
- subtree) {
- if (ec)
+ std::optional<nlohmann::json> pushUriOptions;
+ if (!json_util::readJson(req, asyncResp->res,
+ "HttpPushUriOptions", pushUriOptions))
{
- messages::internalError(asyncResp->res);
return;
}
- asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
- asyncResp->res.jsonValue["Members@odata.count"] = 0;
- for (auto& obj : subtree)
+ if (pushUriOptions)
{
- sdbusplus::message::object_path path(obj.first);
- std::string swId = path.filename();
- if (swId.empty())
+ std::optional<nlohmann::json> pushUriApplyTime;
+ if (!json_util::readJson(*pushUriOptions, asyncResp->res,
+ "HttpPushUriApplyTime",
+ pushUriApplyTime))
+ {
+ return;
+ }
+
+ if (pushUriApplyTime)
+ {
+ std::optional<std::string> applyTime;
+ if (!json_util::readJson(*pushUriApplyTime,
+ asyncResp->res, "ApplyTime",
+ applyTime))
+ {
+ return;
+ }
+
+ if (applyTime)
+ {
+ std::string applyTimeNewVal;
+ if (applyTime == "Immediate")
+ {
+ applyTimeNewVal =
+ "xyz.openbmc_project.Software.ApplyTime."
+ "RequestedApplyTimes.Immediate";
+ }
+ else if (applyTime == "OnReset")
+ {
+ applyTimeNewVal =
+ "xyz.openbmc_project.Software.ApplyTime."
+ "RequestedApplyTimes.OnReset";
+ }
+ else
+ {
+ BMCWEB_LOG_INFO
+ << "ApplyTime value is not in the list of "
+ "acceptable values";
+ messages::propertyValueNotInList(
+ asyncResp->res, *applyTime, "ApplyTime");
+ return;
+ }
+
+ // Set the requested image apply time value
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](
+ const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR
+ << "D-Bus responses error: " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ messages::success(asyncResp->res);
+ },
+ "xyz.openbmc_project.Settings",
+ "/xyz/openbmc_project/software/apply_time",
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Software.ApplyTime",
+ "RequestedApplyTime",
+ std::variant<std::string>{applyTimeNewVal});
+ }
+ }
+ }
+ });
+ BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/")
+ .privileges({"ConfigureComponents"})
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ BMCWEB_LOG_DEBUG << "doPost...";
+
+ // Setup callback for when new software detected
+ monitorForSoftwareAvailable(asyncResp, req,
+ "/redfish/v1/UpdateService");
+
+ std::string filepath("/tmp/images/" +
+ boost::uuids::to_string(
+ boost::uuids::random_generator()()));
+ BMCWEB_LOG_DEBUG << "Writing file to " << filepath;
+ std::ofstream out(filepath, std::ofstream::out |
+ std::ofstream::binary |
+ std::ofstream::trunc);
+ out << req.body;
+ out.close();
+ BMCWEB_LOG_DEBUG << "file upload complete!!";
+ });
+}
+
+inline void requestRoutesSoftwareInventoryCollection(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/FirmwareInventory/")
+ .privileges({"Login"})
+ .methods(boost::beast::http::verb::get)(
+ [](const crow::Request&,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#SoftwareInventoryCollection.SoftwareInventoryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/UpdateService/FirmwareInventory";
+ asyncResp->res.jsonValue["Name"] =
+ "Software Inventory Collection";
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](
+ const boost::system::error_code ec,
+ const std::vector<std::pair<
+ std::string,
+ std::vector<std::pair<std::string,
+ std::vector<std::string>>>>>&
+ subtree) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["Members"] =
+ nlohmann::json::array();
+ asyncResp->res.jsonValue["Members@odata.count"] = 0;
+
+ for (auto& obj : subtree)
+ {
+ sdbusplus::message::object_path path(obj.first);
+ std::string swId = path.filename();
+ if (swId.empty())
+ {
+ messages::internalError(asyncResp->res);
+ BMCWEB_LOG_DEBUG << "Can't parse firmware ID!!";
+ return;
+ }
+
+ nlohmann::json& members =
+ asyncResp->res.jsonValue["Members"];
+ members.push_back(
+ {{"@odata.id", "/redfish/v1/UpdateService/"
+ "FirmwareInventory/" +
+ swId}});
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ members.size();
+ }
+ },
+ // Note that only firmware levels associated with a device
+ // are stored under /xyz/openbmc_project/software therefore
+ // to ensure only real FirmwareInventory items are returned,
+ // this full object path must be used here as input to
+ // mapper
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/software", static_cast<int32_t>(0),
+ std::array<const char*, 1>{
+ "xyz.openbmc_project.Software.Version"});
+ });
+}
+/* Fill related item links (i.e. bmc, bios) in for inventory */
+inline static void
+ getRelatedItems(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+ const std::string& purpose)
+{
+ if (purpose == fw_util::bmcPurpose)
+ {
+ nlohmann::json& relatedItem = aResp->res.jsonValue["RelatedItem"];
+ relatedItem.push_back({{"@odata.id", "/redfish/v1/Managers/bmc"}});
+ aResp->res.jsonValue["RelatedItem@odata.count"] = relatedItem.size();
+ }
+ else if (purpose == fw_util::biosPurpose)
+ {
+ nlohmann::json& relatedItem = aResp->res.jsonValue["RelatedItem"];
+ relatedItem.push_back(
+ {{"@odata.id", "/redfish/v1/Systems/system/Bios"}});
+ aResp->res.jsonValue["Members@odata.count"] = relatedItem.size();
+ }
+ else
+ {
+ BMCWEB_LOG_ERROR << "Unknown software purpose " << purpose;
+ }
+}
+
+inline void requestRoutesSoftwareInventory(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/FirmwareInventory/<str>/")
+ .privileges({"Login"})
+ .methods(
+ boost::beast::http::verb::get)([](const crow::Request&,
+ const std::shared_ptr<
+ bmcweb::AsyncResp>& asyncResp,
+ const std::string& param) {
+ std::shared_ptr<std::string> swId =
+ std::make_shared<std::string>(param);
+
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/UpdateService/FirmwareInventory/" + *swId;
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, swId](
+ const boost::system::error_code ec,
+ const std::vector<
+ std::pair<std::string,
+ std::vector<std::pair<
+ std::string, std::vector<std::string>>>>>&
+ subtree) {
+ BMCWEB_LOG_DEBUG << "doGet callback...";
+ if (ec)
{
messages::internalError(asyncResp->res);
- BMCWEB_LOG_DEBUG << "Can't parse firmware ID!!";
return;
}
- nlohmann::json& members =
- asyncResp->res.jsonValue["Members"];
- members.push_back(
- {{"@odata.id", "/redfish/v1/UpdateService/"
- "FirmwareInventory/" +
- swId}});
- asyncResp->res.jsonValue["Members@odata.count"] =
- members.size();
- }
- },
- // Note that only firmware levels associated with a device are
- // stored under /xyz/openbmc_project/software therefore to ensure
- // only real FirmwareInventory items are returned, this full object
- // path must be used here as input to mapper
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTree",
- "/xyz/openbmc_project/software", static_cast<int32_t>(0),
- std::array<const char*, 1>{"xyz.openbmc_project.Software.Version"});
- }
-};
-
-class SoftwareInventory : public Node
-{
- public:
- SoftwareInventory(App& app) :
- Node(app, "/redfish/v1/UpdateService/FirmwareInventory/<str>/",
- std::string())
- {
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- /* Fill related item links (i.e. bmc, bios) in for inventory */
- static void getRelatedItems(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
- const std::string& purpose)
- {
- if (purpose == fw_util::bmcPurpose)
- {
- nlohmann::json& relatedItem = aResp->res.jsonValue["RelatedItem"];
- relatedItem.push_back({{"@odata.id", "/redfish/v1/Managers/bmc"}});
- aResp->res.jsonValue["RelatedItem@odata.count"] =
- relatedItem.size();
- }
- else if (purpose == fw_util::biosPurpose)
- {
- nlohmann::json& relatedItem = aResp->res.jsonValue["RelatedItem"];
- relatedItem.push_back(
- {{"@odata.id", "/redfish/v1/Systems/system/Bios"}});
- aResp->res.jsonValue["RelatedItem@odata.count"] =
- relatedItem.size();
- }
- else
- {
- BMCWEB_LOG_ERROR << "Unknown software purpose " << purpose;
- }
- }
-
- void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const crow::Request&,
- const std::vector<std::string>& params) override
- {
- if (params.size() != 1)
- {
- messages::internalError(asyncResp->res);
-
- return;
- }
-
- std::shared_ptr<std::string> swId =
- std::make_shared<std::string>(params[0]);
-
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/UpdateService/FirmwareInventory/" + *swId;
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, swId](
- const boost::system::error_code ec,
- const std::vector<std::pair<
- std::string, std::vector<std::pair<
- std::string, std::vector<std::string>>>>>&
- subtree) {
- BMCWEB_LOG_DEBUG << "doGet callback...";
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- // Ensure we find our input swId, otherwise return an error
- bool found = false;
- for (const std::pair<
- std::string,
- std::vector<
- std::pair<std::string, std::vector<std::string>>>>&
- obj : subtree)
- {
- if (boost::ends_with(obj.first, *swId) != true)
+ // Ensure we find our input swId, otherwise return an error
+ bool found = false;
+ for (const std::pair<
+ std::string,
+ std::vector<std::pair<
+ std::string, std::vector<std::string>>>>& obj :
+ subtree)
{
- continue;
- }
+ if (boost::ends_with(obj.first, *swId) != true)
+ {
+ continue;
+ }
- if (obj.second.size() < 1)
+ if (obj.second.size() < 1)
+ {
+ continue;
+ }
+
+ found = true;
+ fw_util::getFwStatus(asyncResp, swId,
+ obj.second[0].first);
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, swId](
+ const boost::system::error_code errorCode,
+ const boost::container::flat_map<
+ std::string, VariantType>& propertiesList) {
+ if (errorCode)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ boost::container::flat_map<
+ std::string, VariantType>::const_iterator
+ it = propertiesList.find("Purpose");
+ if (it == propertiesList.end())
+ {
+ BMCWEB_LOG_DEBUG
+ << "Can't find property \"Purpose\"!";
+ messages::propertyMissing(asyncResp->res,
+ "Purpose");
+ return;
+ }
+ const std::string* swInvPurpose =
+ std::get_if<std::string>(&it->second);
+ if (swInvPurpose == nullptr)
+ {
+ BMCWEB_LOG_DEBUG << "wrong types for "
+ "property\"Purpose\"!";
+ messages::propertyValueTypeError(
+ asyncResp->res, "", "Purpose");
+ return;
+ }
+
+ BMCWEB_LOG_DEBUG << "swInvPurpose = "
+ << *swInvPurpose;
+ it = propertiesList.find("Version");
+ if (it == propertiesList.end())
+ {
+ BMCWEB_LOG_DEBUG
+ << "Can't find property \"Version\"!";
+ messages::propertyMissing(asyncResp->res,
+ "Version");
+ return;
+ }
+
+ BMCWEB_LOG_DEBUG << "Version found!";
+
+ const std::string* version =
+ std::get_if<std::string>(&it->second);
+
+ if (version == nullptr)
+ {
+ BMCWEB_LOG_DEBUG
+ << "Can't find property \"Version\"!";
+
+ messages::propertyValueTypeError(
+ asyncResp->res, "", "Version");
+ return;
+ }
+ asyncResp->res.jsonValue["Version"] = *version;
+ asyncResp->res.jsonValue["Id"] = *swId;
+
+ // swInvPurpose is of format:
+ // xyz.openbmc_project.Software.Version.VersionPurpose.ABC
+ // Translate this to "ABC image"
+ size_t endDesc = swInvPurpose->rfind('.');
+ if (endDesc == std::string::npos)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ endDesc++;
+ if (endDesc >= swInvPurpose->size())
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ std::string formatDesc =
+ swInvPurpose->substr(endDesc);
+ asyncResp->res.jsonValue["Description"] =
+ formatDesc + " image";
+ getRelatedItems(asyncResp, *swInvPurpose);
+ },
+ obj.second[0].first, obj.first,
+ "org.freedesktop.DBus.Properties", "GetAll",
+ "xyz.openbmc_project.Software.Version");
+ }
+ if (!found)
{
- continue;
+ BMCWEB_LOG_ERROR
+ << "Input swID " + *swId + " not found!";
+ messages::resourceMissingAtURI(
+ asyncResp->res,
+ "/redfish/v1/UpdateService/FirmwareInventory/" +
+ *swId);
+ return;
}
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#SoftwareInventory.v1_1_0.SoftwareInventory";
+ asyncResp->res.jsonValue["Name"] = "Software Inventory";
+ asyncResp->res.jsonValue["Status"]["HealthRollup"] = "OK";
- found = true;
- fw_util::getFwStatus(asyncResp, swId, obj.second[0].first);
-
- crow::connections::systemBus->async_method_call(
- [asyncResp,
- swId](const boost::system::error_code errorCode,
- const boost::container::flat_map<
- std::string, VariantType>& propertiesList) {
- if (errorCode)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- boost::container::flat_map<
- std::string, VariantType>::const_iterator it =
- propertiesList.find("Purpose");
- if (it == propertiesList.end())
- {
- BMCWEB_LOG_DEBUG
- << "Can't find property \"Purpose\"!";
- messages::propertyMissing(asyncResp->res,
- "Purpose");
- return;
- }
- const std::string* swInvPurpose =
- std::get_if<std::string>(&it->second);
- if (swInvPurpose == nullptr)
- {
- BMCWEB_LOG_DEBUG
- << "wrong types for property\"Purpose\"!";
- messages::propertyValueTypeError(asyncResp->res,
- "", "Purpose");
- return;
- }
-
- BMCWEB_LOG_DEBUG << "swInvPurpose = "
- << *swInvPurpose;
- it = propertiesList.find("Version");
- if (it == propertiesList.end())
- {
- BMCWEB_LOG_DEBUG
- << "Can't find property \"Version\"!";
- messages::propertyMissing(asyncResp->res,
- "Version");
- return;
- }
-
- BMCWEB_LOG_DEBUG << "Version found!";
-
- const std::string* version =
- std::get_if<std::string>(&it->second);
-
- if (version == nullptr)
- {
- BMCWEB_LOG_DEBUG
- << "Can't find property \"Version\"!";
-
- messages::propertyValueTypeError(asyncResp->res,
- "", "Version");
- return;
- }
- asyncResp->res.jsonValue["Version"] = *version;
- asyncResp->res.jsonValue["Id"] = *swId;
-
- // swInvPurpose is of format:
- // xyz.openbmc_project.Software.Version.VersionPurpose.ABC
- // Translate this to "ABC image"
- size_t endDesc = swInvPurpose->rfind('.');
- if (endDesc == std::string::npos)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- endDesc++;
- if (endDesc >= swInvPurpose->size())
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- std::string formatDesc =
- swInvPurpose->substr(endDesc);
- asyncResp->res.jsonValue["Description"] =
- formatDesc + " image";
- getRelatedItems(asyncResp, *swInvPurpose);
- },
- obj.second[0].first, obj.first,
- "org.freedesktop.DBus.Properties", "GetAll",
- "xyz.openbmc_project.Software.Version");
- }
- if (!found)
- {
- BMCWEB_LOG_ERROR << "Input swID " + *swId + " not found!";
- messages::resourceMissingAtURI(
- asyncResp->res,
- "/redfish/v1/UpdateService/FirmwareInventory/" + *swId);
- return;
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#SoftwareInventory.v1_1_0.SoftwareInventory";
- asyncResp->res.jsonValue["Name"] = "Software Inventory";
- asyncResp->res.jsonValue["Status"]["HealthRollup"] = "OK";
-
- asyncResp->res.jsonValue["Updateable"] = false;
- fw_util::getFwUpdateableStatus(asyncResp, swId);
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/",
- static_cast<int32_t>(0),
- std::array<const char*, 1>{"xyz.openbmc_project.Software.Version"});
- }
-};
+ asyncResp->res.jsonValue["Updateable"] = false;
+ fw_util::getFwUpdateableStatus(asyncResp, swId);
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/",
+ static_cast<int32_t>(0),
+ std::array<const char*, 1>{
+ "xyz.openbmc_project.Software.Version"});
+ });
+}
} // namespace redfish
diff --git a/redfish-core/lib/virtual_media.hpp b/redfish-core/lib/virtual_media.hpp
index 685ee5c..ce40f67 100644
--- a/redfish-core/lib/virtual_media.hpp
+++ b/redfish-core/lib/virtual_media.hpp
@@ -15,6 +15,7 @@
*/
#pragma once
+#include <app.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/process/async_pipe.hpp>
#include <boost/type_traits/has_dereference.hpp>