diff options
author | jmbills <jason.m.bills@intel.com> | 2021-08-31 21:23:16 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-31 21:23:16 +0300 |
commit | 04cd92067d2481643df5010cb39b2134b648cf4d (patch) | |
tree | d98626c9763ad9048ac9bfd8269e12eced18d496 /meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb | |
parent | 10ad77d5bc86709d8ff7f95e7040e39f1c153903 (diff) | |
parent | 6f106a0a4ce15fe0678d4ffefd572e6978c72597 (diff) | |
download | openbmc-04cd92067d2481643df5010cb39b2134b648cf4d.tar.xz |
Update
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb')
34 files changed, 3970 insertions, 1638 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0001-Firmware-update-configuration-changes.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0001-Firmware-update-configuration-changes.patch index a76990262..b689748ea 100755..100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0001-Firmware-update-configuration-changes.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0001-Firmware-update-configuration-changes.patch @@ -1,6 +1,6 @@ -From d5f2e8b00bc5f8a727a1ef678941c4993c3ea7a6 Mon Sep 17 00:00:00 2001 +From c65d6f4a6d2939335608957fba25e5c8a445813e Mon Sep 17 00:00:00 2001 From: Vikram Bodireddy <vikram.bodireddy@intel.com> -Date: Wed, 18 Nov 2020 17:14:41 +0530 +Date: Mon, 28 Jun 2021 21:56:18 +0530 Subject: [PATCH] Firmware update configuration changes This commit will provide user to PATCH the below firmware update @@ -39,24 +39,32 @@ Tested: - Successfully ran redfish validater with no new errors. -Change-Id: I44e1743fd76aa37c7b8affa49a3e05f808187037 Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com> -Signed-off-by: Helen Huang <he.huang@intel.com> -Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com> --- - redfish-core/lib/update_service.hpp | 338 ++++++++++++++++-- + redfish-core/lib/update_service.hpp | 456 ++++++++++++++---- static/redfish/v1/$metadata/index.xml | 3 + - .../JsonSchemas/OemUpdateService/index.json | 69 ++++ - .../redfish/v1/schema/OemUpdateService_v1.xml | 40 +++ - 4 files changed, 421 insertions(+), 29 deletions(-) + .../JsonSchemas/OemUpdateService/index.json | 69 +++ + .../redfish/v1/schema/OemUpdateService_v1.xml | 40 ++ + 4 files changed, 481 insertions(+), 87 deletions(-) create mode 100644 static/redfish/v1/JsonSchemas/OemUpdateService/index.json create mode 100644 static/redfish/v1/schema/OemUpdateService_v1.xml diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp -index ca1234f..0a9f81a 100644 +index 663d48b..70c58d4 100644 --- a/redfish-core/lib/update_service.hpp +++ b/redfish-core/lib/update_service.hpp -@@ -32,6 +32,17 @@ static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateErrorMatcher; +@@ -26,7 +26,9 @@ + + namespace redfish + { +- ++// params for multiple firmware targets ++std::vector<std::string> httpPushUriTargets; ++bool httpPushUriTargetBusy = false; + // Match signals added on software path + static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateMatcher; + static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateErrorMatcher; +@@ -34,6 +36,17 @@ static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateErrorMatcher; static bool fwUpdateInProgress = false; // Timer for software available static std::unique_ptr<boost::asio::steady_timer> fwAvailableTimer; @@ -72,15 +80,15 @@ index ca1234f..0a9f81a 100644 +static constexpr const char* activationsStandBySpare = + "xyz.openbmc_project.Software.Activation.Activations.StandbySpare"; - static void cleanUp() + inline static void cleanUp() { -@@ -40,28 +51,120 @@ static void cleanUp() +@@ -42,28 +55,120 @@ inline static void cleanUp() fwUpdateErrorMatcher = nullptr; } - static void activateImage(const std::string& objPath, -- const std::string& service) -+ const std::string& service, -+ const std::vector<std::string>& imgUriTargets) + inline static void activateImage(const std::string& objPath, +- const std::string& service) ++ const std::string& service, ++ const std::vector<std::string>& imgUriTargets) { BMCWEB_LOG_DEBUG << "Activate image for " << objPath << " " << service; + // If targets is empty, it will apply to the active. @@ -113,14 +121,14 @@ index ca1234f..0a9f81a 100644 + const boost::system::error_code ec, + const crow::openbmc_mapper::GetSubTreeType& subtree) { + if (ec || !subtree.size()) - { -- BMCWEB_LOG_DEBUG << "error_code = " << errorCode; -- BMCWEB_LOG_DEBUG << "error msg = " << errorCode.message(); ++ { + return; + } + + for (const auto& [invObjPath, invDict] : subtree) -+ { + { +- BMCWEB_LOG_DEBUG << "error_code = " << errorCode; +- BMCWEB_LOG_DEBUG << "error msg = " << errorCode.message(); + std::size_t idPos = invObjPath.rfind("/"); + if ((idPos == std::string::npos) || + ((idPos + 1) >= invObjPath.size())) @@ -205,7 +213,7 @@ index ca1234f..0a9f81a 100644 sdbusplus::message::message& m, const crow::Request& req) { -@@ -74,22 +177,24 @@ static void +@@ -76,22 +181,24 @@ static void m.read(objPath, interfacesProperties); @@ -234,7 +242,7 @@ index ca1234f..0a9f81a 100644 BMCWEB_LOG_DEBUG << "error msg = " << errorCode.message(); if (asyncResp) -@@ -116,7 +221,7 @@ static void +@@ -118,7 +225,7 @@ static void // is added fwAvailableTimer = nullptr; @@ -243,7 +251,7 @@ index ca1234f..0a9f81a 100644 if (asyncResp) { std::shared_ptr<task::TaskData> task = -@@ -248,8 +353,7 @@ static void +@@ -250,8 +357,7 @@ static void "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", "xyz.openbmc_project.ObjectMapper", "GetObject", objPath.str, @@ -253,7 +261,7 @@ index ca1234f..0a9f81a 100644 } } } -@@ -259,7 +363,7 @@ static void +@@ -261,7 +367,7 @@ static void static void monitorForSoftwareAvailable( const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const crow::Request& req, const std::string& url, @@ -262,7 +270,7 @@ index ca1234f..0a9f81a 100644 { // Only allow one FW update at a time if (fwUpdateInProgress != false) -@@ -299,9 +403,10 @@ static void monitorForSoftwareAvailable( +@@ -301,9 +407,10 @@ static void monitorForSoftwareAvailable( } }); @@ -275,291 +283,412 @@ index ca1234f..0a9f81a 100644 }; fwUpdateInProgress = true; -@@ -477,12 +582,15 @@ class UpdateServiceActionsSimpleUpdate : public Node - std::string fwFile = imageURI.substr(separator + 1); - BMCWEB_LOG_DEBUG << "Server: " << tftpServer + " File: " << fwFile; +@@ -468,12 +575,15 @@ inline void requestRoutesUpdateServiceActionsSimpleUpdate(App& app) + std::string fwFile = imageURI.substr(separator + 1); + BMCWEB_LOG_DEBUG << "Server: " << tftpServer + " File: " << fwFile; -+ // We will pass empty targets and its handled in activation. -+ std::vector<std::string> httpUriTargets; ++ // We will pass empty targets and its handled in activation. ++ std::vector<std::string> httpUriTargets; + - // Setup callback for when new software detected - // Give TFTP 10 minutes to complete - monitorForSoftwareAvailable( - asyncResp, req, - "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate", -- 600); -+ httpUriTargets, 600); + // Setup callback for when new software detected + // Give TFTP 10 minutes to complete + monitorForSoftwareAvailable( + asyncResp, req, + "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate", +- 600); ++ httpUriTargets, 600); - // TFTP can take up to 10 minutes depending on image size and - // connection speed. Return to caller as soon as the TFTP operation -@@ -516,7 +624,8 @@ class UpdateServiceActionsSimpleUpdate : public Node - class UpdateService : public Node - { - public: -- UpdateService(App& app) : Node(app, "/redfish/v1/UpdateService/") -+ UpdateService(App& app) : -+ Node(app, "/redfish/v1/UpdateService/"), httpPushUriTargetBusy(false) - { - entityPrivileges = { - {boost::beast::http::verb::get, {{"Login"}}}, -@@ -528,6 +637,8 @@ class UpdateService : public Node - } - - private: -+ std::vector<std::string> httpPushUriTargets; -+ bool httpPushUriTargetBusy; - void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const crow::Request&, const std::vector<std::string>&) override - { -@@ -538,6 +649,9 @@ class UpdateService : public Node - asyncResp->res.jsonValue["Description"] = "Service for Software Update"; - asyncResp->res.jsonValue["Name"] = "Update Service"; - asyncResp->res.jsonValue["HttpPushUri"] = "/redfish/v1/UpdateService"; -+ asyncResp->res.jsonValue["HttpPushUriTargets"] = httpPushUriTargets; -+ asyncResp->res.jsonValue["HttpPushUriTargetsBusy"] = -+ httpPushUriTargetBusy; - // UpdateService cannot be disabled - asyncResp->res.jsonValue["ServiceEnabled"] = true; - asyncResp->res.jsonValue["FirmwareInventory"] = { -@@ -587,6 +701,32 @@ class UpdateService : public Node - "/xyz/openbmc_project/software/apply_time", - "org.freedesktop.DBus.Properties", "Get", - "xyz.openbmc_project.Software.ApplyTime", "RequestedApplyTime"); + // TFTP can take up to 10 minutes depending on image size and + // connection speed. Return to caller as soon as the TFTP operation +@@ -522,6 +632,9 @@ inline void requestRoutesUpdateService(App& app) + asyncResp->res.jsonValue["Name"] = "Update Service"; + asyncResp->res.jsonValue["HttpPushUri"] = + "/redfish/v1/UpdateService"; ++ asyncResp->res.jsonValue["HttpPushUriTargets"] = httpPushUriTargets; ++ asyncResp->res.jsonValue["HttpPushUriTargetsBusy"] = ++ httpPushUriTargetBusy; + // UpdateService cannot be disabled + asyncResp->res.jsonValue["ServiceEnabled"] = true; + asyncResp->res.jsonValue["FirmwareInventory"] = { +@@ -536,7 +649,8 @@ inline void requestRoutesUpdateService(App& app) + asyncResp->res + .jsonValue["Actions"]["#UpdateService.SimpleUpdate"]; + updateSvcSimpleUpdate["target"] = +- "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate"; ++ "/redfish/v1/UpdateService/Actions/" ++ "UpdateService.SimpleUpdate"; + updateSvcSimpleUpdate["TransferProtocol@Redfish.AllowableValues"] = + {"TFTP"}; + #endif +@@ -578,89 +692,258 @@ inline void requestRoutesUpdateService(App& app) + "/xyz/openbmc_project/software/apply_time", + "org.freedesktop.DBus.Properties", "Get", + "xyz.openbmc_project.Software.ApplyTime", "RequestedApplyTime"); + -+ // Get the ApplyOptions value -+ crow::connections::systemBus->async_method_call( -+ [asyncResp](const boost::system::error_code ec, -+ const std::variant<bool> applyOption) { -+ if (ec) -+ { -+ BMCWEB_LOG_DEBUG << "DBUS response error " << ec; -+ messages::internalError(asyncResp->res); -+ return; -+ } ++ // Get the ApplyOptions value ++ crow::connections::systemBus->async_method_call( ++ [asyncResp](const boost::system::error_code ec, ++ const std::variant<bool> applyOption) { ++ if (ec) ++ { ++ BMCWEB_LOG_DEBUG << "DBUS response error " << ec; ++ messages::internalError(asyncResp->res); ++ return; ++ } + -+ const bool* b = std::get_if<bool>(&applyOption); ++ const bool* b = std::get_if<bool>(&applyOption); + -+ if (b) -+ { -+ asyncResp->res -+ .jsonValue["Oem"]["ApplyOptions"]["@odata.type"] = -+ "#OemUpdateService.ApplyOptions"; -+ asyncResp->res -+ .jsonValue["Oem"]["ApplyOptions"]["ClearConfig"] = *b; -+ } -+ }, -+ "xyz.openbmc_project.Software.BMC.Updater", -+ "/xyz/openbmc_project/software", "org.freedesktop.DBus.Properties", -+ "Get", "xyz.openbmc_project.Software.ApplyOptions", "ClearConfig"); - } - - void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, -@@ -596,12 +736,61 @@ class UpdateService : public Node - BMCWEB_LOG_DEBUG << "doPatch..."; - - std::optional<nlohmann::json> pushUriOptions; -+ std::optional<std::vector<std::string>> imgTargets; -+ std::optional<bool> imgTargetBusy; -+ std::optional<nlohmann::json> oemProps; ++ if (b) ++ { ++ asyncResp->res ++ .jsonValue["Oem"]["ApplyOptions"]["@odata.type"] = ++ "#OemUpdateService.ApplyOptions"; ++ asyncResp->res ++ .jsonValue["Oem"]["ApplyOptions"]["ClearConfig"] = ++ *b; ++ } ++ }, ++ "xyz.openbmc_project.Software.BMC.Updater", ++ "/xyz/openbmc_project/software", ++ "org.freedesktop.DBus.Properties", "Get", ++ "xyz.openbmc_project.Software.ApplyOptions", "ClearConfig"); + }); + - if (!json_util::readJson(req, asyncResp->res, "HttpPushUriOptions", -- pushUriOptions)) -+ pushUriOptions, "HttpPushUriTargets", -+ imgTargets, "HttpPushUriTargetsBusy", -+ imgTargetBusy, "Oem", oemProps)) - { -+ BMCWEB_LOG_DEBUG << "UpdateService doPatch: Invalid request body"; - return; - } - -+ if (oemProps) -+ { -+ std::optional<nlohmann::json> applyOptions; + BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/") + .privileges(redfish::privileges::patchUpdateService) +- .methods(boost::beast::http::verb::patch)( +- [](const crow::Request& req, +- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { +- BMCWEB_LOG_DEBUG << "doPatch..."; ++ .methods( ++ boost::beast::http::verb:: ++ patch)([](const crow::Request& req, ++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { ++ BMCWEB_LOG_DEBUG << "doPatch..."; + -+ if (!json_util::readJson(*oemProps, asyncResp->res, "ApplyOptions", -+ applyOptions)) ++ std::optional<nlohmann::json> pushUriOptions; ++ std::optional<std::vector<std::string>> imgTargets; ++ std::optional<bool> imgTargetBusy; ++ std::optional<nlohmann::json> oemProps; ++ if (!json_util::readJson(req, asyncResp->res, "HttpPushUriOptions", ++ pushUriOptions, "HttpPushUriTargets", ++ imgTargets, "HttpPushUriTargetsBusy", ++ imgTargetBusy, "Oem", oemProps)) + { ++ BMCWEB_LOG_DEBUG ++ << "UpdateService doPatch: Invalid request body"; + return; + } + -+ if (applyOptions) ++ if (oemProps) + { -+ std::optional<bool> clearConfig; -+ if (!json_util::readJson(*applyOptions, asyncResp->res, -+ "ClearConfig", clearConfig)) ++ std::optional<nlohmann::json> applyOptions; ++ ++ if (!json_util::readJson(*oemProps, asyncResp->res, ++ "ApplyOptions", applyOptions)) + { + return; + } + -+ if (clearConfig) ++ if (applyOptions) + { -+ // 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.Software.BMC.Updater", -+ "/xyz/openbmc_project/software", -+ "org.freedesktop.DBus.Properties", "Set", -+ "xyz.openbmc_project.Software.ApplyOptions", -+ "ClearConfig", std::variant<bool>{*clearConfig}); ++ std::optional<bool> clearConfig; ++ if (!json_util::readJson(*applyOptions, asyncResp->res, ++ "ClearConfig", clearConfig)) ++ { ++ return; ++ } + +- std::optional<nlohmann::json> pushUriOptions; +- if (!json_util::readJson(req, asyncResp->res, +- "HttpPushUriOptions", pushUriOptions)) ++ if (clearConfig) ++ { ++ // 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.Software.BMC.Updater", ++ "/xyz/openbmc_project/software", ++ "org.freedesktop.DBus.Properties", "Set", ++ "xyz.openbmc_project.Software.ApplyOptions", ++ "ClearConfig", std::variant<bool>{*clearConfig}); ++ } + } + } -+ } -+ - if (pushUriOptions) - { - std::optional<nlohmann::json> pushUriApplyTime; -@@ -666,6 +855,98 @@ class UpdateService : public Node - } - } - } -+ -+ if (imgTargetBusy) -+ { -+ if ((httpPushUriTargetBusy) && (*imgTargetBusy)) ++ if (pushUriOptions) + { -+ BMCWEB_LOG_DEBUG -+ << "Other client has reserved the HttpPushUriTargets " -+ "property for firmware updates."; -+ messages::resourceInUse(asyncResp->res); -+ return; ++ std::optional<nlohmann::json> pushUriApplyTime; ++ if (!json_util::readJson(*pushUriOptions, asyncResp->res, ++ "HttpPushUriApplyTime", ++ pushUriApplyTime)) + { + return; + } + +- if (pushUriOptions) ++ if (pushUriApplyTime) + { +- std::optional<nlohmann::json> pushUriApplyTime; +- if (!json_util::readJson(*pushUriOptions, asyncResp->res, +- "HttpPushUriApplyTime", +- pushUriApplyTime)) ++ std::optional<std::string> applyTime; ++ if (!json_util::readJson(*pushUriApplyTime, asyncResp->res, ++ "ApplyTime", applyTime)) + { + return; + } + +- if (pushUriApplyTime) ++ if (applyTime) + { +- std::optional<std::string> applyTime; +- if (!json_util::readJson(*pushUriApplyTime, +- asyncResp->res, "ApplyTime", +- 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; + } + +- if (applyTime) ++ // 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}); ++ } ++ } + } -+ -+ if (imgTargets) ++ if (imgTargetBusy) + { -+ if (!(*imgTargetBusy)) ++ if ((httpPushUriTargetBusy) && (*imgTargetBusy)) + { + BMCWEB_LOG_DEBUG -+ << "UpdateService doPatch: httpPushUriTargetBusy " -+ "should be " -+ "true before setting httpPushUriTargets"; -+ messages::invalidObject(asyncResp->res, -+ "HttpPushUriTargetsBusy"); ++ << "Other client has reserved the HttpPushUriTargets " ++ "property for firmware updates."; ++ messages::resourceInUse(asyncResp->res); + return; + } -+ if ((*imgTargets).size() != 0) ++ ++ if (imgTargets) + { -+ // TODO: Now we support max one target becuase -+ // software-manager code support one activation per object. -+ // It will be enhanced to multiple targets for single image -+ // in future. For now, consider first target alone. -+ if ((*imgTargets).size() != 1) ++ if (!(*imgTargetBusy)) + { ++ BMCWEB_LOG_DEBUG ++ << "UpdateService doPatch: httpPushUriTargetBusy " ++ "should be " ++ "true before setting httpPushUriTargets"; + messages::invalidObject(asyncResp->res, -+ "HttpPushUriTargets"); ++ "HttpPushUriTargetsBusy"); + return; + } -+ crow::connections::systemBus->async_method_call( -+ [this, asyncResp, uriTargets{*imgTargets}, -+ targetBusy{*imgTargetBusy}]( -+ const boost::system::error_code ec, -+ const std::vector<std::string> swInvPaths) { -+ if (ec) -+ { -+ return; -+ } -+ -+ bool swInvObjFound = false; -+ for (const std::string& path : swInvPaths) -+ { -+ std::size_t idPos = path.rfind("/"); -+ if ((idPos == std::string::npos) || -+ ((idPos + 1) >= path.size())) ++ if ((*imgTargets).size() != 0) ++ { ++ // TODO: Now we support max one target becuase ++ // software-manager code support one activation per ++ // object. It will be enhanced to multiple targets for ++ // single image in future. For now, consider first ++ // target alone. ++ if ((*imgTargets).size() != 1) + { +- 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; +- } ++ messages::invalidObject(asyncResp->res, ++ "HttpPushUriTargets"); ++ return; ++ } ++ crow::connections::systemBus->async_method_call( ++ [asyncResp, uriTargets{*imgTargets}, ++ targetBusy{*imgTargetBusy}]( ++ const boost::system::error_code ec, ++ const std::vector<std::string> swInvPaths) { ++ if (ec) + { -+ messages::internalError(asyncResp->res); -+ BMCWEB_LOG_DEBUG -+ << "Can't parse firmware ID!!"; + return; + } -+ std::string swId = path.substr(idPos + 1); + +- // Set the requested image apply time value +- crow::connections::systemBus->async_method_call( +- [asyncResp]( +- const boost::system::error_code ec) { +- if (ec) ++ bool swInvObjFound = false; ++ for (const std::string& path : swInvPaths) ++ { ++ std::size_t idPos = path.rfind("/"); ++ if ((idPos == std::string::npos) || ++ ((idPos + 1) >= path.size())) + { +- BMCWEB_LOG_ERROR +- << "D-Bus responses error: " << ec; + messages::internalError(asyncResp->res); ++ BMCWEB_LOG_DEBUG ++ << "Can't parse firmware ID!!"; + 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}); +- } ++ std::string swId = path.substr(idPos + 1); + -+ if (swId == uriTargets[0]) ++ if (swId == uriTargets[0]) ++ { ++ swInvObjFound = true; ++ break; ++ } ++ } ++ if (!swInvObjFound) + { -+ swInvObjFound = true; -+ break; ++ messages::invalidObject( ++ asyncResp->res, "HttpPushUriTargets"); ++ return; + } -+ } -+ if (!swInvObjFound) -+ { -+ messages::invalidObject(asyncResp->res, -+ "HttpPushUriTargets"); -+ return; -+ } -+ this->httpPushUriTargetBusy = targetBusy; -+ this->httpPushUriTargets = uriTargets; -+ }, -+ "xyz.openbmc_project.ObjectMapper", -+ "/xyz/openbmc_project/object_mapper", -+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", -+ "/", static_cast<int32_t>(0), -+ std::array<const char*, 1>{versionIntf}); -+ } ++ httpPushUriTargetBusy = targetBusy; ++ httpPushUriTargets = uriTargets; ++ }, ++ "xyz.openbmc_project.ObjectMapper", ++ "/xyz/openbmc_project/object_mapper", ++ "xyz.openbmc_project.ObjectMapper", ++ "GetSubTreePaths", "/", static_cast<int32_t>(0), ++ std::array<const char*, 1>{versionIntf}); ++ } ++ else ++ { ++ httpPushUriTargetBusy = *imgTargetBusy; ++ httpPushUriTargets = *imgTargets; + } + } +- }); + else + { + httpPushUriTargetBusy = *imgTargetBusy; -+ httpPushUriTargets = *imgTargets; + } + } -+ else -+ { -+ httpPushUriTargetBusy = *imgTargetBusy; -+ } -+ } - } - - void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, -@@ -675,8 +956,8 @@ class UpdateService : public Node - BMCWEB_LOG_DEBUG << "doPost..."; ++ }); ++ + BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/") + .privileges(redfish::privileges::postUpdateService) + .methods(boost::beast::http::verb::post)( +@@ -670,7 +953,8 @@ inline void requestRoutesUpdateService(App& app) - // Setup callback for when new software detected -- monitorForSoftwareAvailable(asyncResp, req, -- "/redfish/v1/UpdateService"); -+ monitorForSoftwareAvailable(asyncResp, req, "/redfish/v1/UpdateService", -+ httpPushUriTargets); + // Setup callback for when new software detected + monitorForSoftwareAvailable(asyncResp, req, +- "/redfish/v1/UpdateService"); ++ "/redfish/v1/UpdateService", ++ httpPushUriTargets); - std::string filepath( - "/tmp/images/" + -@@ -759,7 +1040,7 @@ class SoftwareInventoryCollection : public Node - "/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"}); -+ std::array<const char*, 1>{versionIntf}); - } - }; + std::string filepath("/tmp/images/" + + boost::uuids::to_string( +@@ -683,7 +967,7 @@ inline void requestRoutesUpdateService(App& app) + out.close(); + BMCWEB_LOG_DEBUG << "file upload complete!!"; + }); +-} ++} // namespace redfish -@@ -940,7 +1221,7 @@ class SoftwareInventory : public Node - }, - obj.second[0].first, obj.first, - "org.freedesktop.DBus.Properties", "GetAll", -- "xyz.openbmc_project.Software.Version"); -+ versionIntf); - } - if (!found) - { -@@ -961,8 +1242,7 @@ class SoftwareInventory : public Node - "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"}); -+ static_cast<int32_t>(0), std::array<const char*, 1>{versionIntf}); - } - }; + inline void requestRoutesSoftwareInventoryCollection(App& app) + { +@@ -746,8 +1030,7 @@ inline void requestRoutesSoftwareInventoryCollection(App& app) + "/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"}); ++ std::array<const char*, 1>{versionIntf}); + }); + } + /* Fill related item links (i.e. bmc, bios) in for inventory */ +@@ -911,7 +1194,7 @@ inline void requestRoutesSoftwareInventory(App& app) + }, + obj.second[0].first, obj.first, + "org.freedesktop.DBus.Properties", "GetAll", +- "xyz.openbmc_project.Software.Version"); ++ versionIntf); + } + if (!found) + { +@@ -935,8 +1218,7 @@ inline void requestRoutesSoftwareInventory(App& app) + "/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"}); ++ std::array<const char*, 1>{versionIntf}); + }); + } diff --git a/static/redfish/v1/$metadata/index.xml b/static/redfish/v1/$metadata/index.xml -index 9d9fd1f..6cbc0d1 100644 +index eba38bf..876ebfb 100644 --- a/static/redfish/v1/$metadata/index.xml +++ b/static/redfish/v1/$metadata/index.xml -@@ -2145,6 +2145,9 @@ +@@ -2346,6 +2346,9 @@ <edmx:Reference Uri="/redfish/v1/schema/OemComputerSystem_v1.xml"> <edmx:Include Namespace="OemComputerSystem"/> </edmx:Reference> diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0010-managers-add-attributes-for-Manager.CommandShell.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0010-managers-add-attributes-for-Manager.CommandShell.patch index d962d3872..e54e495bb 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0010-managers-add-attributes-for-Manager.CommandShell.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0010-managers-add-attributes-for-Manager.CommandShell.patch @@ -1,6 +1,6 @@ -From b5e4edfc26eec245427d3435de9acaa9363ae836 Mon Sep 17 00:00:00 2001 -From: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com> -Date: Mon, 28 Dec 2020 18:55:57 +0000 +From 971aa5058ac4bb626eeadf8b00738737748ed549 Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> +Date: Tue, 29 Jun 2021 15:25:38 +0000 Subject: [PATCH] managers: add attributes for Manager.CommandShell Issue: ConnectTypesSupported, ServiceEnabled and @@ -31,37 +31,30 @@ Response: .... Signed-off-by: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com> +Change-Id: I2a56db912fc81064098f7aa9f4d110ac3baf361d --- - redfish-core/lib/managers.hpp | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) + redfish-core/lib/managers.hpp | 8 ++++++++ + 1 file changed, 8 insertions(+) diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp -index 67f8d99..dcbc347 100644 +index b286f19..186003b 100644 --- a/redfish-core/lib/managers.hpp +++ b/redfish-core/lib/managers.hpp -@@ -1830,6 +1830,13 @@ class Manager : public Node - asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15; - asyncResp->res.jsonValue["SerialConsole"]["ConnectTypesSupported"] = { - "IPMI", "SSH"}; +@@ -1998,6 +1998,14 @@ inline void requestRoutesManager(App& app) + 15; + asyncResp->res.jsonValue["SerialConsole"]["ConnectTypesSupported"] = + {"IPMI", "SSH"}; + -+ // Fill in CommandShell info -+ asyncResp->res.jsonValue["CommandShell"]["ServiceEnabled"] = true; -+ asyncResp->res.jsonValue["CommandShell"]["MaxConcurrentSessions"] = 4; -+ asyncResp->res.jsonValue["CommandShell"]["ConnectTypesSupported"] = { -+ "SSH", "IPMI"}; ++ // Fill in CommandShell info ++ asyncResp->res.jsonValue["CommandShell"]["ServiceEnabled"] = true; ++ asyncResp->res.jsonValue["CommandShell"]["MaxConcurrentSessions"] = ++ 4; ++ asyncResp->res.jsonValue["CommandShell"]["ConnectTypesSupported"] = ++ {"SSH", "IPMI"}; + #ifdef BMCWEB_ENABLE_KVM - // Fill in GraphicalConsole info - asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true; -@@ -2272,7 +2279,7 @@ class Manager : public Node - } - - std::string uuid; --}; -+}; // namespace redfish - - class ManagerCollection : public Node - { + // Fill in GraphicalConsole info + asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = -- -2.17.1 +2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0019-Add-generic-message-PropertySizeExceeded.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0019-Add-generic-message-PropertySizeExceeded.patch index 756ea24d7..028119249 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0019-Add-generic-message-PropertySizeExceeded.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0019-Add-generic-message-PropertySizeExceeded.patch @@ -1,6 +1,6 @@ -From da893566ec02aefe235685f1b6742269aab37909 Mon Sep 17 00:00:00 2001 -From: Nitin Wankhade <nitinx.arunrao.wankhade@intel.com> -Date: Thu, 24 Jun 2021 15:29:24 +0000 +From 2b865ad20ce0616b79a453d1571976bb2303050c Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> +Date: Wed, 14 Jul 2021 13:55:27 +0000 Subject: [PATCH] Add generic message - PropertySizeExceeded Adding a generic error message "PropertySizeExceeded" @@ -19,13 +19,13 @@ Signed-off-by: Nitin Wankhade <nitinx.arunrao.wankhade@intel.com> 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/redfish-core/include/error_messages.hpp b/redfish-core/include/error_messages.hpp -index 922dae9..586246c 100644 +index 922dae9..f29e326 100644 --- a/redfish-core/include/error_messages.hpp +++ b/redfish-core/include/error_messages.hpp @@ -222,6 +222,18 @@ nlohmann::json propertyValueFormatError(const std::string& arg1, void propertyValueFormatError(crow::Response& res, const std::string& arg1, const std::string& arg2); - + +/** + * @brief Formats PropertySizeExceeded message into JSON + * Message body: "The property <arg1> is too long. The value exceeds its size @@ -42,19 +42,19 @@ index 922dae9..586246c 100644 * @brief Formats PropertyValueNotInList message into JSON * Message body: "The value <arg1> for the property <arg2> is not in the list of diff --git a/redfish-core/include/registries/base_message_registry.hpp b/redfish-core/include/registries/base_message_registry.hpp -index 7c385a0..79d324e 100644 +index 58156c8..ab9b046 100644 --- a/redfish-core/include/registries/base_message_registry.hpp +++ b/redfish-core/include/registries/base_message_registry.hpp @@ -36,7 +36,7 @@ const Header header = { constexpr const char* url = - "https://redfish.dmtf.org/registries/Base.1.8.1.json"; - --constexpr std::array<MessageEntry, 74> registry = { -+constexpr std::array<MessageEntry, 75> registry = { + "https://redfish.dmtf.org/registries/Base.1.10.0.json"; + +-constexpr std::array<MessageEntry, 87> registry = { ++constexpr std::array<MessageEntry, 88> registry = { MessageEntry{ "AccessDenied", { -@@ -592,6 +592,21 @@ constexpr std::array<MessageEntry, 74> registry = { +@@ -664,6 +664,21 @@ constexpr std::array<MessageEntry, 87> registry = { "Remove the property from the request body and resubmit " "the request if the operation failed.", }}, @@ -77,13 +77,13 @@ index 7c385a0..79d324e 100644 { "Indicates that an unknown property was included in the " diff --git a/redfish-core/src/error_messages.cpp b/redfish-core/src/error_messages.cpp -index 409adb1..11e59be 100644 +index 409adb1..bebb6d8 100644 --- a/redfish-core/src/error_messages.cpp +++ b/redfish-core/src/error_messages.cpp @@ -514,6 +514,33 @@ void propertyValueFormatError(crow::Response& res, const std::string& arg1, addMessageToJson(res.jsonValue, propertyValueFormatError(arg1, arg2), arg2); } - + +/** + * @internal + * @brief Formats PropertySizeExceeded message into JSON for the specified @@ -114,5 +114,6 @@ index 409adb1..11e59be 100644 /** * @internal * @brief Formats PropertyValueNotInList message into JSON for the specified -2.17.1 +-- +2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0020-Redfish-Deny-set-AccountLockDuration-to-zero.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0020-Redfish-Deny-set-AccountLockDuration-to-zero.patch new file mode 100644 index 000000000..cc9da3b8b --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0020-Redfish-Deny-set-AccountLockDuration-to-zero.patch @@ -0,0 +1,85 @@ +From f75efac9eebea8bf8f548d10a8cbafa28f556a8f Mon Sep 17 00:00:00 2001 +From: Meera-Katta <meerax.katta@linux.intel.com> +Date: Wed, 7 Jul 2021 13:19:09 +0000 +Subject: [PATCH] Redfish: Deny set AccountLockDuration to zero +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Issue: Redfish schema says, no lockout shall occur in case of Account +LockoutDuration value is zero. But Linux PAM module documentation says, if +account lockout value is zero, account will be locked out indefinitely +after the number of failed login attempts. As per the current +implementation user can write any value into the PAM module. If user tried +to set unlock timeout value to zero, account will be locked out +indefinitely until administrator explicitly reenables it. + +Workaround: Denying user to set AccountLockDuration to zero from Redfish. +Setting ‘AccountLockDuration’ to 0 will be permitted only after +‘AccountLockoutCounterResetEnabled’ support is added. +Otherwise,account will be locked permanently after the AccountLockoutDuration +if ‘AccountLockDuration’ is set to zero, while +AccountLockoutThreshold is non zero. If someone wants no account lockout +irrespective of number of failed login attempts, it can be still achieved by +setting ‘AccountLockoutThreshold’ to zero +(instead of trying to set ‘AccountLockDuration’ to zero.) + +Tested: +1) Redfish Service Validator passed for this change. +2) Verified from Redfish +PATCH : https://<BMC IP>/redfish/v1/AccountService +Body: +{"AccountLockoutDuration":0} + +Response: +{ + "AccountLockoutDuration@Message.ExtendedInfo": [ + { + "@odata.type": "#Message.v1_1_1.Message", + "Message": "The value unlockTimeout for the property + AccountLockoutDuration is not in the list of acceptable values.", + "MessageArgs": [ + "unlockTimeout", + "AccountLockoutDuration" + ], + "MessageId": "Base.1.8.1.PropertyValueNotInList", + "MessageSeverity": "Warning", + "Resolution": "Choose a value from the enumeration list that the + implementation can support and resubmit the request if the + operation failed." + } + ] +} + +Signed-off-by: Meera-Katta <meerax.katta@linux.intel.com> +--- + redfish-core/lib/account_service.hpp | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp +index e6fe205..42085fa 100644 +--- a/redfish-core/lib/account_service.hpp ++++ b/redfish-core/lib/account_service.hpp +@@ -1448,6 +1448,19 @@ inline void requestAccountServiceRoutes(App& app) + + if (unlockTimeout) + { ++ // Account will be locked permanently after the N number ++ // of failed login attempts if we set unlockTimeout value ++ // to be 0. ++ if (unlockTimeout.value() == 0) ++ { ++ BMCWEB_LOG_INFO ++ << "Unlock timeout value must be greater" ++ "than zero"; ++ messages::propertyValueNotInList(asyncResp->res, ++ "unlockTimeout", ++ "AccountLockoutDuration"); ++ return; ++ } + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec) { + if (ec) +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0021-Add-message-registry-entry-for-FirmwareResiliencyErr.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0021-Add-message-registry-entry-for-FirmwareResiliencyErr.patch new file mode 100644 index 000000000..2b8f8987c --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0021-Add-message-registry-entry-for-FirmwareResiliencyErr.patch @@ -0,0 +1,84 @@ +From 35c9f6f0f4e1254f0512154cc46116d8047fe19b Mon Sep 17 00:00:00 2001 +From: Chalapathi Venkataramashetty <chalapathix.venkataramashetty@intel.com> +Date: Wed, 14 Jul 2021 20:44:06 +0000 +Subject: [PATCH] Add message registry entry for FirmwareResiliencyError + +Add an event log in redfish when firmware update failed due to +FirmwareResiliencyError. + +The existing message entries BMCFirmwareResiliencyError(for BMC update +failures) and BIOSFirmwareResiliencyError(for BIOS update failures) are +not useful for the new platform. The new platform's CPLD report common +error code for BMC, PCH or CPLD firmware update failures. Hence a common +message entry is required to capture the firmware update failure events. + +This event is Implemented in the following review. +https://gerrit.openbmc-project.xyz/c/openbmc/pfr-manager/+/43281 + +Tested: +Redfish Service Validator passed for this change. + +Update BMC firmware with mismatched SVN +POST: https://<BMC_IP>/redfish/v1/UpdateService/ + with <BMC_Update_Capsule> binary file +After BMC reboots check for Event log in Redfish +Command: GET: https://<BMC_IP>/redfish/v1/Systems/system/LogServices/ + EventLog/Entries +Response: +{ + "@odata.id": "/redfish/v1/Systems/system/LogServices/ + EventLog/Entries/1621435142_1", + "@odata.type": "#LogEntry.v1_4_0.LogEntry", + "Created": "2021-05-19T14:39:02+00:00", + "EntryType": "Event", + "Id": "1621435142_1", + "Message": "Firmware resiliency error. Error reason: + Firmware update failed(MinorCode:0x02).", + "MessageArgs": [ + "Firmware update failed(MinorCode:0x02)" + ], + "MessageId": "OpenBMC.0.1.FirmwareResiliencyError", + "Name": "System Event Log Entry", + "Severity": "Critical" + }, + +Signed-off-by: Chalapathi Venkataramashetty <chalapathix.venkataramashetty@intel.com> +--- + .../registries/openbmc_message_registry.hpp | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/redfish-core/include/registries/openbmc_message_registry.hpp b/redfish-core/include/registries/openbmc_message_registry.hpp +index a00d235..967713f 100644 +--- a/redfish-core/include/registries/openbmc_message_registry.hpp ++++ b/redfish-core/include/registries/openbmc_message_registry.hpp +@@ -29,7 +29,7 @@ const Header header = { + "0.2.0", + "OpenBMC", + }; +-constexpr std::array<MessageEntry, 196> registry = { ++constexpr std::array<MessageEntry, 197> registry = { + MessageEntry{ + "ADDDCCorrectable", + { +@@ -560,6 +560,18 @@ constexpr std::array<MessageEntry, 196> registry = { + {"string"}, + "None.", + }}, ++ MessageEntry{"FirmwareResiliencyError", ++ { ++ "Indicates firmware encountered resilience error.", ++ "Firmware resiliency error. Error reason: %1.", ++ "Critical", ++ "Critical", ++ 1, ++ { ++ "string", ++ }, ++ "None.", ++ }}, + MessageEntry{"FirmwareUpdateCompleted", + { + "Indicates a firmware update has completed successfully.", +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0023-Add-get-IPMI-session-id-s-to-Redfish.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0023-Add-get-IPMI-session-id-s-to-Redfish.patch new file mode 100644 index 000000000..b3feee39a --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0023-Add-get-IPMI-session-id-s-to-Redfish.patch @@ -0,0 +1,390 @@ +From 5c79e34be9357c2a2cd9bac61cd0162dbd342a2d Mon Sep 17 00:00:00 2001 +From: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com> +Date: Fri, 30 Jul 2021 17:33:16 +0000 +Subject: [PATCH] Add/get IPMI session id's to Redfish + +As per existing implementation, Redfish supports to get only sessions +created on Redfish & EWS. But as per Redfish schema Redfish should +include to get IPMI sessions as well. +So add support to display IPMI session Id's as well on Redfish. +This commit will not impact any functionality/behavior of existing code. +Below functionalities implemented in this commit. +1. Get IPMI session collection +2. Get individual IPMI session information +3. Delete IPMI sessions - Respond with not supported as we can't delete + IPMI sessions from Redfish interface + +Tested: +1. Verified redfish validator passed with active IPMI session. +2. Get session details from Redfish +GET: https://<BMC-IP>/redfish/v1/SessionService/Sessions +Response: +{ + "@odata.id": "/redfish/v1/SessionService/Sessions/", + "@odata.type": "#SessionCollection.SessionCollection", + "Description": "Session Collection", + "Members": [ + { + "@odata.id": "/redfish/v1/SessionService/Sessions/TlFPbR9ZIn" + }, + { + "@odata.id": "/redfish/v1/SessionService/Sessions/184U3014ub" + }, + { + "@odata.id": "/redfish/v1/SessionService/Sessions/cV0xi5QoPy" + }, + { + "@odata.id": "/redfish/v1/SessionService/Sessions/8f6234d7_81" + } + ], + "Members@odata.count": 4, + "Name": "Session Collection" +} + +3. Get session details from RedFish +Case 1: RedFish session +GET: https://<BMC-IP>/redfish/v1/SessionService/Sessions/TlFPbR9ZIn +Response: +{ + "@odata.id": "/redfish/v1/SessionService/Sessions/TlFPbR9ZIn", + "@odata.type": "#Session.v1_3_0.Session", + "ClientOriginIPAddress": "::ffff:10.213.91.40", + "Description": "Manager User Session", + "Id": "TlFPbR9ZIn", + "Name": "User Session", + "UserName": "root" +} +Case 2: IPMI session +Verified and displayed IPMI session details on RedFish. +GET: https://<BMC-IP>/redfish/v1/SessionService/Sessions/8f6234d7_81 +Response: +{ + "@odata.id": "/redfish/v1/SessionService/Sessions/8f6234d7_81", + "@odata.type": "#Session.v1_3_0.Session", + "ClientOriginIPAddress": "xx.xx.xx.xx", + "Description": "Manager User Session", + "Id": "8f6234d7_81", + "Name": "User Session", + "UserName": "root" +} +4. Delete IPMI session: +Verified IPMI session is not allowed to delete from Redfish +DELETE: https://<BMC-IP>/redfish/v1/SessionService/Sessions/8f6234d7_81 +Response: +{ + "error": { + "@Message.ExtendedInfo": [ + { + "@odata.type": "#Message.v1_1_1.Message", + "Message": "The action deleting IPMI session from + Redfish is not supported by the resource.", + "MessageArgs": [ + "deleting IPMI session from Redfish" + ], + "MessageId": "Base.1.8.1.ActionNotSupported", + "MessageSeverity": "Critical", + "Resolution": "The action supplied cannot be resubmitted + to the implementation. Perhaps the action was invalid, + the wrong resource was the target or the implementation + documentation may be of assistance." + } + ], + "code": "Base.1.8.1.ActionNotSupported", + "message": "The action deleting IPMI session from Redfish is not + supported by the resource." + } +} +5. Delete RedFish session +Result: successfully deleted valid RedFish session. + +Signed-off-by: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com> +--- + redfish-core/lib/redfish_sessions.hpp | 244 +++++++++++++++++++++++--- + 1 file changed, 222 insertions(+), 22 deletions(-) + +diff --git a/redfish-core/lib/redfish_sessions.hpp b/redfish-core/lib/redfish_sessions.hpp +index 929e0c8..3c7a968 100644 +--- a/redfish-core/lib/redfish_sessions.hpp ++++ b/redfish-core/lib/redfish_sessions.hpp +@@ -56,14 +56,127 @@ inline void requestRoutesSession(App& app) + auto session = persistent_data::SessionStore::getInstance() + .getSessionByUid(sessionId); + +- if (session == nullptr) ++ if (session) + { +- messages::resourceNotFound(asyncResp->res, "Session", +- sessionId); ++ fillSessionObject(asyncResp->res, *session); + return; + } + +- fillSessionObject(asyncResp->res, *session); ++ std::array<std::string, 1> interfaces = { ++ "xyz.openbmc_project.Ipmi.SessionInfo"}; ++ crow::connections::systemBus->async_method_call( ++ [asyncResp, sessionId](const boost::system::error_code ec, ++ const GetSubTreeType& subtree) { ++ if (ec) ++ { ++ BMCWEB_LOG_DEBUG ++ << "Error in querying GetSubTree with " ++ "Object Mapper. " ++ << ec; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ if (subtree.size() == 0) ++ { ++ BMCWEB_LOG_DEBUG ++ << "Can't find Session Info Attributes!"; ++ messages::resourceNotFound(asyncResp->res, ++ "Session", sessionId); ++ return; ++ } ++ bool ipmiSessionFound = false; ++ std::string ipmiSessionService; ++ std::string ipmiSessionInfPath; ++ for (const auto& [ipmiSessionPath, object] : subtree) ++ { ++ if (ipmiSessionPath.empty() || object.empty()) ++ { ++ BMCWEB_LOG_DEBUG ++ << "Session Info Attributes mapper error!"; ++ continue; ++ } ++ if (!boost::ends_with(ipmiSessionPath, sessionId)) ++ { ++ continue; ++ } ++ ipmiSessionFound = true; ++ ipmiSessionService = object[0].first; ++ ipmiSessionInfPath = ipmiSessionPath; ++ break; ++ } ++ if (!ipmiSessionFound) ++ { ++ messages::resourceNotFound(asyncResp->res, ++ "Session", sessionId); ++ return; ++ } ++ if (ipmiSessionService.empty()) ++ { ++ BMCWEB_LOG_DEBUG ++ << "Session Info Attributes mapper " ++ "error!"; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ crow::connections::systemBus->async_method_call( ++ [asyncResp, sessionId]( ++ const boost::system::error_code ec, ++ const std::vector<std::pair< ++ std::string, ++ std::variant<std::monostate, std::string, ++ uint32_t>>>& properties) { ++ if (ec) ++ { ++ BMCWEB_LOG_DEBUG ++ << "Error in querying Session " ++ "Info State property " ++ << ec; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ std::string userName = ""; ++ uint32_t remoteIpAddr; ++ try ++ { ++ sdbusplus::unpackProperties( ++ properties, "Username", userName, ++ "RemoteIPAddr", remoteIpAddr); ++ asyncResp->res.jsonValue["Id"] = sessionId; ++ asyncResp->res.jsonValue["UserName"] = ++ userName; ++ asyncResp->res.jsonValue["@odata.id"] = ++ "/redfish/v1/SessionService/" ++ "Sessions/" + ++ sessionId; ++ asyncResp->res.jsonValue["@odata.type"] = ++ "#Session.v1_3_0.Session"; ++ asyncResp->res.jsonValue["Name"] = ++ "User Session"; ++ asyncResp->res.jsonValue["Description"] = ++ "Manager User Session"; ++ struct in_addr ipAddr; ++ ipAddr.s_addr = remoteIpAddr; ++ asyncResp->res ++ .jsonValue["ClientOriginIPAddress"] = ++ inet_ntoa(ipAddr); ++ } ++ catch (const sdbusplus::exception:: ++ UnpackPropertyError& error) ++ { ++ BMCWEB_LOG_ERROR << error.what(); ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ return; ++ }, ++ ipmiSessionService, ipmiSessionInfPath, ++ "org.freedesktop.DBus.Properties", "GetAll", ++ "xyz.openbmc_project.Ipmi.SessionInfo"); ++ }, ++ "xyz.openbmc_project.ObjectMapper", ++ "/xyz/openbmc_project/object_mapper", ++ "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", 0, ++ interfaces); + }); + + BMCWEB_ROUTE(app, "/redfish/v1/SessionService/Sessions/<str>/") +@@ -75,34 +188,79 @@ inline void requestRoutesSession(App& app) + auto session = persistent_data::SessionStore::getInstance() + .getSessionByUid(sessionId); + +- if (session == nullptr) +- { +- messages::resourceNotFound(asyncResp->res, "Session", +- sessionId); +- return; +- } +- + // Perform a proper ConfigureSelf authority check. If a + // session is being used to DELETE some other user's session, + // then the ConfigureSelf privilege does not apply. In that + // case, perform the authority check again without the user's + // ConfigureSelf privilege. +- if (session->username != req.session->username) ++ if (session) + { +- Privileges effectiveUserPrivileges = +- redfish::getUserPrivileges(req.userRole); +- +- if (!effectiveUserPrivileges.isSupersetOf( +- {"ConfigureUsers"})) ++ if (session->username != req.session->username) + { +- messages::insufficientPrivilege(asyncResp->res); +- return; ++ Privileges effectiveUserPrivileges = ++ redfish::getUserPrivileges(req.userRole); ++ ++ if (!effectiveUserPrivileges.isSupersetOf( ++ {"ConfigureUsers"})) ++ { ++ messages::insufficientPrivilege(asyncResp->res); ++ return; ++ } + } ++ persistent_data::SessionStore::getInstance().removeSession( ++ session); ++ messages::success(asyncResp->res); ++ return; + } + +- persistent_data::SessionStore::getInstance().removeSession( +- session); +- messages::success(asyncResp->res); ++ std::array<std::string, 1> interfaces = { ++ "xyz.openbmc_project.Ipmi.SessionInfo"}; ++ crow::connections::systemBus->async_method_call( ++ [asyncResp, ++ sessionId](const boost::system::error_code ec, ++ const std::vector<std::string>& ifaceList) { ++ if (ec) ++ { ++ BMCWEB_LOG_DEBUG ++ << "Error in querying GetSubTreePaths " ++ "with Object Mapper. " ++ << ec; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ if (ifaceList.size() == 0) ++ { ++ BMCWEB_LOG_DEBUG ++ << "Can't find Session Info Attributes!"; ++ return; ++ } ++ bool ipmiSessionFound = false; ++ for (const std::string& ipmiSessionPath : ifaceList) ++ { ++ if (!boost::ends_with(ipmiSessionPath, sessionId)) ++ { ++ continue; ++ } ++ ipmiSessionFound = true; ++ break; ++ } ++ if (ipmiSessionFound) ++ { ++ BMCWEB_LOG_DEBUG << "Deleting IPMI session from " ++ "Redfish is not allowed."; ++ messages::actionNotSupported( ++ asyncResp->res, ++ "deleting IPMI session from Redfish"); ++ return; ++ } ++ messages::resourceNotFound(asyncResp->res, "Session", ++ sessionId); ++ return; ++ }, ++ "xyz.openbmc_project.ObjectMapper", ++ "/xyz/openbmc_project/object_mapper", ++ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/", ++ 0, interfaces); + }); + + BMCWEB_ROUTE(app, "/redfish/v1/SessionService/Sessions/") +@@ -131,6 +289,48 @@ inline void requestRoutesSession(App& app) + "/redfish/v1/SessionService/Sessions/"; + asyncResp->res.jsonValue["Name"] = "Session Collection"; + asyncResp->res.jsonValue["Description"] = "Session Collection"; ++ ++ std::array<std::string, 1> interfaces = { ++ "xyz.openbmc_project.Ipmi.SessionInfo"}; ++ crow::connections::systemBus->async_method_call( ++ [asyncResp](const boost::system::error_code ec, ++ const std::vector<std::string>& ifaceList) { ++ if (ec) ++ { ++ BMCWEB_LOG_DEBUG ++ << "Error in querying GetSubTreePaths " ++ "with Object Mapper. " ++ << ec; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ if (ifaceList.size() == 0) ++ { ++ BMCWEB_LOG_DEBUG ++ << "Can't find Session Info Attributes!"; ++ return; ++ } ++ for (const std::string& ipmiSessionPath : ifaceList) ++ { ++ std::filesystem::path filePath(ipmiSessionPath); ++ std::string ipmiSessionID = ++ filePath.has_filename() ? filePath.filename() ++ : ""; ++ if (!ipmiSessionID.empty() && ipmiSessionID != "0") ++ { ++ asyncResp->res.jsonValue["Members"].push_back( ++ {{"@odata.id", ++ "/redfish/v1/SessionService/Sessions/" + ++ ipmiSessionID}}); ++ } ++ } ++ asyncResp->res.jsonValue["Members@odata.count"] = ++ asyncResp->res.jsonValue["Members"].size(); ++ }, ++ "xyz.openbmc_project.ObjectMapper", ++ "/xyz/openbmc_project/object_mapper", ++ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/", ++ 0, interfaces); + }); + + BMCWEB_ROUTE(app, "/redfish/v1/SessionService/Sessions/") +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0024-Add-count-sensor-type.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0024-Add-count-sensor-type.patch new file mode 100644 index 000000000..a9a4ab151 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0024-Add-count-sensor-type.patch @@ -0,0 +1,29 @@ +From fb337f868543f72bd8ba24db3c4b09b4c1d888ab Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Adrian=20Ambro=C5=BCewicz?= <adrian.ambrozewicz@intel.com> +Date: Fri, 30 Jul 2021 15:25:29 +0200 +Subject: [PATCH] Add 'count' sensor type + +PMT exposes data mainly in raw counter formats. This change makes +bmcweb aware of new sensor type. + +Testing: +- values of type 'count' from PMT exposed successfully on Redfish +--- + redfish-core/lib/sensors.hpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp +index cb7ea15..d72a572 100644 +--- a/redfish-core/lib/sensors.hpp ++++ b/redfish-core/lib/sensors.hpp +@@ -63,6 +63,7 @@ static const boost::container::flat_map<std::string_view, + {node::sensors, + {"/xyz/openbmc_project/sensors/power", + "/xyz/openbmc_project/sensors/current", ++ "/xyz/openbmc_project/sensors/count", + "/xyz/openbmc_project/sensors/airflow", + "/xyz/openbmc_project/sensors/utilization"}}, + {node::thermal, +-- +2.25.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0025-Revert-Support-new-boot-override-setting-design.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0025-Revert-Support-new-boot-override-setting-design.patch new file mode 100644 index 000000000..e0664a350 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0025-Revert-Support-new-boot-override-setting-design.patch @@ -0,0 +1,723 @@ +From c6ed122a09b1e41b9eab0032ff428b8b1a999534 Mon Sep 17 00:00:00 2001 +From: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com> +Date: Wed, 4 Aug 2021 15:50:34 -0700 +Subject: [PATCH] Revert "Support new boot override setting design" + +This reverts commit c21865c469cfc9dffdc15d87710293115cf6d9e4. + +Change-Id: Icfd03551dd9ea2fb216519d8ab05b92521838542 +Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com> +--- + redfish-core/lib/systems.hpp | 493 +++++++++++++++++------------------ + 1 file changed, 245 insertions(+), 248 deletions(-) + +diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp +index fc6e2c78fd1f..5ad065b3518a 100644 +--- a/redfish-core/lib/systems.hpp ++++ b/redfish-core/lib/systems.hpp +@@ -769,8 +769,11 @@ inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp, + const std::string& rfSource, + std::string& bootSource, std::string& bootMode) + { +- bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default"; +- bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular"; ++ // The caller has initialized the bootSource and bootMode to: ++ // bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular"; ++ // bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default"; ++ // Only modify the bootSource/bootMode variable needed to achieve the ++ // desired boot action. + + if (rfSource == "None") + { +@@ -917,14 +920,45 @@ inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp) + } + + /** +- * @brief Retrieves boot override type over DBUS and fills out the response ++ * @brief Checks if the current boot override state can be considered as ++ * Disabled + * + * @param[in] aResp Shared pointer for generating response message. + * + * @return None. + */ ++inline void ++ checkIfOverrideIsDisabled(const std::shared_ptr<bmcweb::AsyncResp>& aResp) ++{ ++ // If the BootSourceOverrideTarget is still "None" at the end, ++ // reset the BootSourceOverrideEnabled to indicate that ++ // overrides are disabled ++ if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] == "None") ++ { ++ // If the BootSourceOverrideMode is supported we should ++ // check if it is still "UEFI" too ++ if (aResp->res.jsonValue["Boot"].contains("BootSourceOverrideMode")) ++ { ++ if (aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] != ++ "UEFI") ++ { ++ return; ++ } ++ } ++ aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled"; ++ } ++} + +-inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp) ++/** ++ * @brief Retrieves boot type over DBUS and fills out the response ++ * ++ * @param[in] aResp Shared pointer for generating response message. ++ * @param[in] bootDbusObj The dbus object to query for boot properties. ++ * ++ * @return None. ++ */ ++inline void getBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp, ++ const std::string& bootDbusObj) + { + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec, +@@ -932,6 +966,12 @@ inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp) + if (ec) + { + // not an error, don't have to have the interface ++ ++ // Support Disabled override state in a way: ++ // "BootSourceOverrideEnabled=Disabled" = ++ // "BootSourceOverrideMode=UEFI" + ++ // "BootSourceOverrideTarget=None" ++ checkIfOverrideIsDisabled(aResp); + return; + } + +@@ -958,26 +998,31 @@ inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp) + } + + aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType; ++ ++ // Support Disabled override state in a way: ++ // "BootSourceOverrideEnabled=Disabled" = ++ // "BootSourceOverrideMode=UEFI" + "BootSourceOverrideTarget=None" ++ checkIfOverrideIsDisabled(aResp); + }, +- "xyz.openbmc_project.Settings", +- "/xyz/openbmc_project/control/host0/boot", ++ "xyz.openbmc_project.Settings", bootDbusObj, + "org.freedesktop.DBus.Properties", "Get", + "xyz.openbmc_project.Control.Boot.Type", "BootType"); + } + + /** +- * @brief Retrieves boot override mode over DBUS and fills out the response ++ * @brief Retrieves boot mode over DBUS and fills out the response + * + * @param[in] aResp Shared pointer for generating response message. ++ * @param[in] bootDbusObj The dbus object to query for boot properties. + * + * @return None. + */ +- +-inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp) ++inline void getBootMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp, ++ const std::string& bootDbusObj) + { + crow::connections::systemBus->async_method_call( +- [aResp](const boost::system::error_code ec, +- const std::variant<std::string>& bootMode) { ++ [aResp, bootDbusObj](const boost::system::error_code ec, ++ const std::variant<std::string>& bootMode) { + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; +@@ -1010,27 +1055,39 @@ inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp) + rfMode; + } + } ++ ++ // Get BootType inside this async call as we need all of the ++ // BootSource/BootMode/BootType to support ++ // "BootSourceOverrideEnabled"="Disabled" state. ++ getBootType(aResp, bootDbusObj); + }, +- "xyz.openbmc_project.Settings", +- "/xyz/openbmc_project/control/host0/boot", ++ "xyz.openbmc_project.Settings", bootDbusObj, + "org.freedesktop.DBus.Properties", "Get", + "xyz.openbmc_project.Control.Boot.Mode", "BootMode"); + } + + /** +- * @brief Retrieves boot override source over DBUS ++ * @brief Retrieves boot source over DBUS + * + * @param[in] aResp Shared pointer for generating response message. ++ * @param[in] oneTimeEnable Boolean to indicate boot properties are one-time. + * + * @return None. + */ +- +-inline void +- getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp) ++inline void getBootSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp, ++ bool oneTimeEnabled) + { ++ std::string bootDbusObj = ++ oneTimeEnabled ? "/xyz/openbmc_project/control/host0/boot/one_time" ++ : "/xyz/openbmc_project/control/host0/boot"; ++ ++ BMCWEB_LOG_DEBUG << "Is one time: " << oneTimeEnabled; ++ aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = ++ (oneTimeEnabled) ? "Once" : "Continuous"; ++ + crow::connections::systemBus->async_method_call( +- [aResp](const boost::system::error_code ec, +- const std::variant<std::string>& bootSource) { ++ [aResp, bootDbusObj](const boost::system::error_code ec, ++ const std::variant<std::string>& bootSource) { + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; +@@ -1057,43 +1114,32 @@ inline void + + // Get BootMode as BootSourceOverrideTarget is constructed + // from both BootSource and BootMode +- getBootOverrideMode(aResp); ++ getBootMode(aResp, bootDbusObj); + }, +- "xyz.openbmc_project.Settings", +- "/xyz/openbmc_project/control/host0/boot", ++ "xyz.openbmc_project.Settings", bootDbusObj, + "org.freedesktop.DBus.Properties", "Get", + "xyz.openbmc_project.Control.Boot.Source", "BootSource"); + } + + /** +- * @brief This functions abstracts all the logic behind getting a +- * "BootSourceOverrideEnabled" property from an overall boot override enable +- * state ++ * @brief Retrieves "One time" enabled setting over DBUS and calls function to ++ * get boot source and boot mode. + * + * @param[in] aResp Shared pointer for generating response message. + * + * @return None. + */ +- +-inline void +- processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp, +- const bool bootOverrideEnableSetting) ++inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp) + { +- if (!bootOverrideEnableSetting) +- { +- aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled"; +- return; +- } ++ BMCWEB_LOG_DEBUG << "Get boot information."; + +- // If boot source override is enabled, we need to check 'one_time' +- // property to set a correct value for the "BootSourceOverrideEnabled" + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec, + const std::variant<bool>& oneTime) { + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; +- messages::internalError(aResp->res); ++ // not an error, don't have to have the interface + return; + } + +@@ -1104,19 +1150,7 @@ inline void + messages::internalError(aResp->res); + return; + } +- +- bool oneTimeSetting = *oneTimePtr; +- +- if (oneTimeSetting) +- { +- aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = +- "Once"; +- } +- else +- { +- aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = +- "Continuous"; +- } ++ getBootSource(aResp, *oneTimePtr); + }, + "xyz.openbmc_project.Settings", + "/xyz/openbmc_project/control/host0/boot/one_time", +@@ -1124,60 +1158,6 @@ inline void + "xyz.openbmc_project.Object.Enable", "Enabled"); + } + +-/** +- * @brief Retrieves boot override enable over DBUS +- * +- * @param[in] aResp Shared pointer for generating response message. +- * +- * @return None. +- */ +- +-inline void +- getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp) +-{ +- crow::connections::systemBus->async_method_call( +- [aResp](const boost::system::error_code ec, +- const std::variant<bool>& bootOverrideEnable) { +- if (ec) +- { +- BMCWEB_LOG_DEBUG << "DBUS response error " << ec; +- messages::internalError(aResp->res); +- return; +- } +- +- const bool* bootOverrideEnablePtr = +- std::get_if<bool>(&bootOverrideEnable); +- +- if (!bootOverrideEnablePtr) +- { +- messages::internalError(aResp->res); +- return; +- } +- +- processBootOverrideEnable(aResp, *bootOverrideEnablePtr); +- }, +- "xyz.openbmc_project.Settings", +- "/xyz/openbmc_project/control/host0/boot", +- "org.freedesktop.DBus.Properties", "Get", +- "xyz.openbmc_project.Object.Enable", "Enabled"); +-} +- +-/** +- * @brief Retrieves boot source override properties +- * +- * @param[in] aResp Shared pointer for generating response message. +- * +- * @return None. +- */ +-inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp) +-{ +- BMCWEB_LOG_DEBUG << "Get boot information."; +- +- getBootOverrideSource(aResp); +- getBootOverrideType(aResp); +- getBootOverrideEnable(aResp); +-} +- + /** + * @brief Retrieves the Last Reset Time + * +@@ -1479,47 +1459,59 @@ inline void getTrustedModuleRequiredToBoot( + * @brief Sets boot properties into DBUS object(s). + * + * @param[in] aResp Shared pointer for generating response message. ++ * @param[in] overrideEnabled The source override "enable". ++ * @param[in] bootObj Path to the DBUS object. + * @param[in] bootType The boot type to set. + * @return Integer error code. + */ + inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp, ++ const bool overrideEnabled, const std::string& bootObj, + const std::optional<std::string>& bootType) + { +- std::string bootTypeStr; +- +- if (!bootType) +- { +- return; +- } ++ std::string bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI"; + +- // Source target specified +- BMCWEB_LOG_DEBUG << "Boot type: " << *bootType; +- // Figure out which DBUS interface and property to use +- if (*bootType == "Legacy") +- { +- bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy"; +- } +- else if (*bootType == "UEFI") ++ if (bootType && overrideEnabled) + { +- bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI"; +- } +- else +- { +- BMCWEB_LOG_DEBUG << "Invalid property value for " +- "BootSourceOverrideMode: " +- << *bootType; +- messages::propertyValueNotInList(aResp->res, *bootType, +- "BootSourceOverrideMode"); +- return; ++ // Source target specified ++ BMCWEB_LOG_DEBUG << "Boot type: " << *bootType; ++ // Figure out which DBUS interface and property to use ++ if (*bootType == "Legacy") ++ { ++ bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy"; ++ } ++ else if (*bootType == "UEFI") ++ { ++ bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI"; ++ } ++ else ++ { ++ BMCWEB_LOG_DEBUG << "Invalid property value for " ++ "BootSourceOverrideMode: " ++ << *bootType; ++ messages::propertyValueNotInList(aResp->res, *bootType, ++ "BootSourceOverrideMode"); ++ return; ++ } + } + + // Act on validated parameters + BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr; + + crow::connections::systemBus->async_method_call( +- [aResp](const boost::system::error_code ec) { ++ [aResp, bootType](const boost::system::error_code ec) { + if (ec) + { ++ if (!bootType) ++ { ++ // If bootType wasn't explicitly present in the incoming ++ // message don't output error. The error could come from a ++ // fact that the BootType interface may be not present in ++ // the settings object. It could happen because this ++ // interface is not relevant for some Host architectures ++ // (for example POWER). ++ return; ++ } ++ + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + if (ec.value() == boost::asio::error::host_unreachable) + { +@@ -1531,8 +1523,7 @@ inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp, + } + BMCWEB_LOG_DEBUG << "Boot type update done."; + }, +- "xyz.openbmc_project.Settings", +- "/xyz/openbmc_project/control/host0/boot", ++ "xyz.openbmc_project.Settings", bootObj, + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Control.Boot.Type", "BootType", + std::variant<std::string>(bootTypeStr)); +@@ -1542,48 +1533,42 @@ inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp, + * @brief Sets boot properties into DBUS object(s). + * + * @param[in] aResp Shared pointer for generating response message. +- * @param[in] bootType The boot type to set. ++ * @param[in] overrideEnabled The source override "enable". ++ * @param[in] bootObj Path to the DBUS object. ++ * @param[in] bootSource The boot source to set. ++ * + * @return Integer error code. + */ +-inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp, +- const std::optional<std::string>& bootEnable) ++inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp, ++ const bool overrideEnabled, ++ const std::string& bootObj, ++ const std::optional<std::string>& bootSource) + { +- if (!bootEnable) +- { +- return; +- } +- // Source target specified +- BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable; ++ std::string bootSourceStr = ++ "xyz.openbmc_project.Control.Boot.Source.Sources.Default"; ++ std::string bootModeStr = ++ "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular"; + +- bool bootOverrideEnable = false; +- bool bootOverridePersistent = false; +- // Figure out which DBUS interface and property to use +- if (*bootEnable == "Disabled") +- { +- bootOverrideEnable = false; +- } +- else if (*bootEnable == "Once") +- { +- bootOverrideEnable = true; +- bootOverridePersistent = false; +- } +- else if (*bootEnable == "Continuous") ++ if (bootSource && overrideEnabled) + { +- bootOverrideEnable = true; +- bootOverridePersistent = true; +- } +- else +- { +- BMCWEB_LOG_DEBUG << "Invalid property value for " +- "BootSourceOverrideEnabled: " +- << *bootEnable; +- messages::propertyValueNotInList(aResp->res, *bootEnable, +- "BootSourceOverrideEnabled"); +- return; ++ // Source target specified ++ BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource; ++ // Figure out which DBUS interface and property to use ++ if (assignBootParameters(aResp, *bootSource, bootSourceStr, ++ bootModeStr)) ++ { ++ BMCWEB_LOG_DEBUG ++ << "Invalid property value for BootSourceOverrideTarget: " ++ << *bootSource; ++ messages::propertyValueNotInList(aResp->res, *bootSource, ++ "BootSourceTargetOverride"); ++ return; ++ } + } + + // Act on validated parameters +- BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable; ++ BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr; ++ BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr; + + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec) { +@@ -1593,23 +1578,12 @@ inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp, + messages::internalError(aResp->res); + return; + } +- BMCWEB_LOG_DEBUG << "Boot override enable update done."; ++ BMCWEB_LOG_DEBUG << "Boot source update done."; + }, +- "xyz.openbmc_project.Settings", +- "/xyz/openbmc_project/control/host0/boot", ++ "xyz.openbmc_project.Settings", bootObj, + "org.freedesktop.DBus.Properties", "Set", +- "xyz.openbmc_project.Object.Enable", "Enabled", +- std::variant<bool>(bootOverrideEnable)); +- +- if (!bootOverrideEnable) +- { +- return; +- } +- +- // In case boot override is enabled we need to set correct value for the +- // 'one_time' enable DBus interface +- BMCWEB_LOG_DEBUG << "DBUS boot override persistent: " +- << bootOverridePersistent; ++ "xyz.openbmc_project.Control.Boot.Source", "BootSource", ++ std::variant<std::string>(bootSourceStr)); + + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec) { +@@ -1619,86 +1593,45 @@ inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp, + messages::internalError(aResp->res); + return; + } +- BMCWEB_LOG_DEBUG << "Boot one_time update done."; ++ BMCWEB_LOG_DEBUG << "Boot mode update done."; + }, +- "xyz.openbmc_project.Settings", +- "/xyz/openbmc_project/control/host0/boot/one_time", ++ "xyz.openbmc_project.Settings", bootObj, + "org.freedesktop.DBus.Properties", "Set", +- "xyz.openbmc_project.Object.Enable", "Enabled", +- std::variant<bool>(!bootOverridePersistent)); ++ "xyz.openbmc_project.Control.Boot.Mode", "BootMode", ++ std::variant<std::string>(bootModeStr)); + } + + /** +- * @brief Sets boot properties into DBUS object(s). ++ * @brief Sets "One time" enabled setting into DBUS object + * +- * @param[in] aResp Shared pointer for generating response message. +- * @param[in] bootSource The boot source to set. ++ * @param[in] aResp Shared pointer for generating response message. ++ * @param[in] oneTime Enable property for one-time object + * + * @return Integer error code. + */ +-inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp, +- const std::optional<std::string>& bootSource) ++inline void setOneTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp, ++ bool oneTime) + { +- std::string bootSourceStr; +- std::string bootModeStr; +- +- if (!bootSource) +- { +- return; +- } +- +- // Source target specified +- BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource; +- // Figure out which DBUS interface and property to use +- if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr)) +- { +- BMCWEB_LOG_DEBUG +- << "Invalid property value for BootSourceOverrideTarget: " +- << *bootSource; +- messages::propertyValueNotInList(aResp->res, *bootSource, +- "BootSourceTargetOverride"); +- return; +- } +- +- // Act on validated parameters +- BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr; +- BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr; +- + crow::connections::systemBus->async_method_call( +- [aResp](const boost::system::error_code ec) { ++ [aResp{aResp}](const boost::system::error_code ec) { + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } +- BMCWEB_LOG_DEBUG << "Boot source update done."; ++ BMCWEB_LOG_DEBUG << "Boot enable update done."; + }, + "xyz.openbmc_project.Settings", +- "/xyz/openbmc_project/control/host0/boot", +- "org.freedesktop.DBus.Properties", "Set", +- "xyz.openbmc_project.Control.Boot.Source", "BootSource", +- std::variant<std::string>(bootSourceStr)); +- +- crow::connections::systemBus->async_method_call( +- [aResp](const boost::system::error_code ec) { +- if (ec) +- { +- BMCWEB_LOG_DEBUG << "DBUS response error " << ec; +- messages::internalError(aResp->res); +- return; +- } +- BMCWEB_LOG_DEBUG << "Boot mode update done."; +- }, +- "xyz.openbmc_project.Settings", +- "/xyz/openbmc_project/control/host0/boot", ++ "/xyz/openbmc_project/control/host0/boot/one_time", + "org.freedesktop.DBus.Properties", "Set", +- "xyz.openbmc_project.Control.Boot.Mode", "BootMode", +- std::variant<std::string>(bootModeStr)); ++ "xyz.openbmc_project.Object.Enable", "Enabled", ++ std::variant<bool>(oneTime)); + } + + /** +- * @brief Sets Boot source override properties. ++ * @brief Retrieves "One time" enabled setting over DBUS and calls function to ++ * set boot source/boot mode properties. + * + * @param[in] aResp Shared pointer for generating response message. + * @param[in] bootSource The boot source from incoming RF request. +@@ -1707,17 +1640,81 @@ inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp, + * + * @return Integer error code. + */ +- +-inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp, +- const std::optional<std::string>& bootSource, +- const std::optional<std::string>& bootType, +- const std::optional<std::string>& bootEnable) ++inline void ++ setBootSourceProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp, ++ std::optional<std::string> bootSource, ++ std::optional<std::string> bootType, ++ std::optional<std::string> bootEnable) + { + BMCWEB_LOG_DEBUG << "Set boot information."; + +- setBootModeOrSource(aResp, bootSource); +- setBootType(aResp, bootType); +- setBootEnable(aResp, bootEnable); ++ crow::connections::systemBus->async_method_call( ++ [aResp, bootSource{std::move(bootSource)}, ++ bootType{std::move(bootType)}, ++ bootEnable{std::move(bootEnable)}](const boost::system::error_code ec, ++ const std::variant<bool>& oneTime) { ++ if (ec) ++ { ++ BMCWEB_LOG_DEBUG << "DBUS response error " << ec; ++ messages::internalError(aResp->res); ++ return; ++ } ++ ++ const bool* oneTimePtr = std::get_if<bool>(&oneTime); ++ ++ if (!oneTimePtr) ++ { ++ messages::internalError(aResp->res); ++ return; ++ } ++ ++ BMCWEB_LOG_DEBUG << "Got one time: " << *oneTimePtr; ++ ++ bool oneTimeSetting = *oneTimePtr; ++ bool overrideEnabled = true; ++ ++ // Validate incoming parameters ++ if (bootEnable) ++ { ++ if (*bootEnable == "Once") ++ { ++ oneTimeSetting = true; ++ } ++ else if (*bootEnable == "Continuous") ++ { ++ oneTimeSetting = false; ++ } ++ else if (*bootEnable == "Disabled") ++ { ++ BMCWEB_LOG_DEBUG << "Boot source override will be disabled"; ++ oneTimeSetting = false; ++ overrideEnabled = false; ++ } ++ else ++ { ++ BMCWEB_LOG_DEBUG << "Unsupported value for " ++ "BootSourceOverrideEnabled: " ++ << *bootEnable; ++ messages::propertyValueNotInList( ++ aResp->res, *bootEnable, "BootSourceOverrideEnabled"); ++ return; ++ } ++ } ++ ++ std::string bootObj = "/xyz/openbmc_project/control/host0/boot"; ++ if (oneTimeSetting) ++ { ++ bootObj += "/one_time"; ++ } ++ ++ setBootModeOrSource(aResp, overrideEnabled, bootObj, bootSource); ++ setBootType(aResp, overrideEnabled, bootObj, bootType); ++ setOneTime(aResp, oneTimeSetting); ++ }, ++ "xyz.openbmc_project.Settings", ++ "/xyz/openbmc_project/control/host0/boot/one_time", ++ "org.freedesktop.DBus.Properties", "Get", ++ "xyz.openbmc_project.Object.Enable", "Enabled"); + } + + /** +@@ -2806,11 +2803,11 @@ inline void requestRoutesSystems(App& app) + { + return; + } +- + if (bootSource || bootType || bootEnable) + { +- setBootProperties(asyncResp, bootSource, bootType, +- bootEnable); ++ setBootSourceProperties( ++ asyncResp, std::move(bootSource), ++ std::move(bootType), std::move(bootEnable)); + } + if (automaticRetryConfig) + { +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0001-Define-Redfish-interface-Registries-Bios.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0001-Define-Redfish-interface-Registries-Bios.patch index 9cf4653d6..93bbb7494 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0001-Define-Redfish-interface-Registries-Bios.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0001-Define-Redfish-interface-Registries-Bios.patch @@ -1,7 +1,7 @@ -From 72c273ae74bb6add062b89f59ebeee4d4eb7e523 Mon Sep 17 00:00:00 2001 +From 501003876765f51799152bace657d97b7fa2b60e Mon Sep 17 00:00:00 2001 From: Kuiying Wang <kuiying.wang@intel.com> Date: Fri, 4 Sep 2020 19:24:25 +0800 -Subject: [PATCH] Define Redfish interface "/Registries/Bios" and enable +Subject: [PATCH 1/5] Define Redfish interface "/Registries/Bios" and enable Attributes property 1. Define Redfish interface "/Registries/Bios" for BIOS Attribute Registry @@ -227,25 +227,25 @@ Change-Id: Iecc61018c350f0b8c89df59b2864b941508b1916 Signed-off-by: Kuiying Wang <kuiying.wang@intel.com> --- redfish-core/include/redfish.hpp | 2 + - .../include/registries/bios_registry.hpp | 31 ++ - redfish-core/lib/bios.hpp | 501 ++++++++++++++++++ - redfish-core/lib/message_registries.hpp | 9 +- - 4 files changed, 542 insertions(+), 1 deletion(-) + .../include/registries/bios_registry.hpp | 31 + + redfish-core/lib/bios.hpp | 528 ++++++++++++++++++ + redfish-core/lib/message_registries.hpp | 6 + + 4 files changed, 567 insertions(+) create mode 100644 redfish-core/include/registries/bios_registry.hpp diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp -index db58d60..298ebb8 100644 +index c15062d..3388498 100644 --- a/redfish-core/include/redfish.hpp +++ b/redfish-core/include/redfish.hpp -@@ -156,6 +156,8 @@ class RedfishService - 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<BiosSettings>(app)); -+ nodes.emplace_back(std::make_unique<BiosAttributeRegistry>(app)); - nodes.emplace_back(std::make_unique<BiosReset>(app)); +@@ -152,6 +152,8 @@ class RedfishService + requestRoutesSystemActionsReset(app); + requestRoutesSystemResetActionInfo(app); + requestRoutesBiosService(app); ++ requestRoutesBiosSettings(app); ++ requestRoutesBiosAttributeRegistry(app); + requestRoutesBiosReset(app); + #ifdef BMCWEB_ENABLE_VM_NBDPROXY - nodes.emplace_back(std::make_unique<VirtualMedia>(app)); diff --git a/redfish-core/include/registries/bios_registry.hpp b/redfish-core/include/registries/bios_registry.hpp new file mode 100644 index 0000000..88ef782 @@ -285,12 +285,12 @@ index 0000000..88ef782 +} // namespace redfish::message_registries::bios \ No newline at end of file diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp -index 0917cc7..cb2b74d 100644 +index 604b8e7..c1a5c56 100644 --- a/redfish-core/lib/bios.hpp +++ b/redfish-core/lib/bios.hpp @@ -3,8 +3,140 @@ - #include "node.hpp" - + #include <app.hpp> + #include <registries/privilege_registry.hpp> #include <utils/fw_utils.hpp> + namespace redfish @@ -429,420 +429,435 @@ index 0917cc7..cb2b74d 100644 /** * BiosService class supports handle get method for bios. */ -@@ -33,6 +165,375 @@ class BiosService : public Node - // Get the ActiveSoftwareImage and SoftwareImages - fw_util::populateFirmwareInformation(asyncResp, fw_util::biosPurpose, - "", true); -+ asyncResp->res.jsonValue["@Redfish.Settings"] = { -+ {"@odata.type", "#Settings.v1_3_0.Settings"}, -+ {"SettingsObject", -+ {{"@odata.id", "/redfish/v1/Systems/system/Bios/Settings"}}}}; -+ asyncResp->res.jsonValue["AttributeRegistry"] = "BiosAttributeRegistry"; -+ asyncResp->res.jsonValue["Attributes"] = {}; -+ -+ crow::connections::systemBus->async_method_call( -+ [asyncResp](const boost::system::error_code ec, -+ const GetObjectType& getObjectType) { -+ if (ec) -+ { -+ BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " -+ << ec; -+ messages::internalError(asyncResp->res); -+ -+ return; -+ } -+ const std::string& service = getObjectType.begin()->first; +@@ -29,8 +161,404 @@ inline void requestRoutesBiosService(App& app) + // Get the ActiveSoftwareImage and SoftwareImages + fw_util::populateFirmwareInformation( + asyncResp, fw_util::biosPurpose, "", true); ++ asyncResp->res.jsonValue["@Redfish.Settings"] = { ++ {"@odata.type", "#Settings.v1_3_0.Settings"}, ++ {"SettingsObject", ++ {{"@odata.id", ++ "/redfish/v1/Systems/system/Bios/Settings"}}}}; ++ asyncResp->res.jsonValue["AttributeRegistry"] = ++ "BiosAttributeRegistry"; ++ asyncResp->res.jsonValue["Attributes"] = {}; + + crow::connections::systemBus->async_method_call( -+ [asyncResp]( -+ const boost::system::error_code ec, -+ const std::variant<BiosBaseTableType>& retBiosTable) { ++ [asyncResp](const boost::system::error_code ec, ++ const GetObjectType& getObjectType) { + if (ec) + { -+ BMCWEB_LOG_ERROR << "getBiosAttributes DBUS error: " -+ << ec; -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ const BiosBaseTableType* baseBiosTable = -+ std::get_if<BiosBaseTableType>(&retBiosTable); -+ nlohmann::json& attributesJson = -+ asyncResp->res.jsonValue["Attributes"]; -+ if (baseBiosTable == nullptr) -+ { -+ BMCWEB_LOG_ERROR << "baseBiosTable == nullptr "; ++ BMCWEB_LOG_ERROR ++ << "ObjectMapper::GetObject call failed: " ++ << ec; + messages::internalError(asyncResp->res); ++ + return; + } -+ for (const BiosBaseTableItemType& item : *baseBiosTable) -+ { -+ const std::string& key = item.first; -+ const std::string& itemType = -+ std::get<biosBaseAttrType>(item.second); -+ std::string attrType = -+ mapAttrTypeToRedfish(itemType); -+ if (attrType == "String") -+ { -+ const std::string* currValue = -+ std::get_if<std::string>( -+ &std::get<biosBaseCurrValue>( -+ item.second)); -+ attributesJson.emplace(key, currValue != nullptr -+ ? *currValue -+ : ""); -+ } -+ else if (attrType == "Integer") -+ { -+ const int64_t* currValue = std::get_if<int64_t>( -+ &std::get<biosBaseCurrValue>(item.second)); -+ attributesJson.emplace( -+ key, currValue != nullptr ? *currValue : 0); -+ } -+ else -+ { -+ BMCWEB_LOG_ERROR -+ << "Unsupported attribute type."; -+ messages::internalError(asyncResp->res); -+ } -+ } ++ const std::string& service = ++ getObjectType.begin()->first; ++ ++ crow::connections::systemBus->async_method_call( ++ [asyncResp](const boost::system::error_code ec, ++ const std::variant<BiosBaseTableType>& ++ retBiosTable) { ++ if (ec) ++ { ++ BMCWEB_LOG_ERROR ++ << "getBiosAttributes DBUS error: " ++ << ec; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ const BiosBaseTableType* baseBiosTable = ++ std::get_if<BiosBaseTableType>( ++ &retBiosTable); ++ nlohmann::json& attributesJson = ++ asyncResp->res.jsonValue["Attributes"]; ++ if (baseBiosTable == nullptr) ++ { ++ BMCWEB_LOG_ERROR ++ << "baseBiosTable == nullptr "; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ for (const BiosBaseTableItemType& item : ++ *baseBiosTable) ++ { ++ const std::string& key = item.first; ++ const std::string& itemType = ++ std::get<biosBaseAttrType>(item.second); ++ std::string attrType = ++ mapAttrTypeToRedfish(itemType); ++ if (attrType == "String") ++ { ++ const std::string* currValue = ++ std::get_if<std::string>( ++ &std::get<biosBaseCurrValue>( ++ item.second)); ++ attributesJson.emplace( ++ key, currValue != nullptr ++ ? *currValue ++ : ""); ++ } ++ else if (attrType == "Integer") ++ { ++ const int64_t* currValue = ++ std::get_if<int64_t>( ++ &std::get<biosBaseCurrValue>( ++ item.second)); ++ attributesJson.emplace( ++ key, currValue != nullptr ++ ? *currValue ++ : 0); ++ } ++ else ++ { ++ BMCWEB_LOG_ERROR ++ << "Unsupported attribute type."; ++ messages::internalError(asyncResp->res); ++ } ++ } ++ }, ++ service, "/xyz/openbmc_project/bios_config/manager", ++ "org.freedesktop.DBus.Properties", "Get", ++ "xyz.openbmc_project.BIOSConfig.Manager", ++ "BaseBIOSTable"); + }, -+ service, "/xyz/openbmc_project/bios_config/manager", -+ "org.freedesktop.DBus.Properties", "Get", -+ "xyz.openbmc_project.BIOSConfig.Manager", "BaseBIOSTable"); -+ }, -+ "xyz.openbmc_project.ObjectMapper", -+ "/xyz/openbmc_project/object_mapper", -+ "xyz.openbmc_project.ObjectMapper", "GetObject", -+ "/xyz/openbmc_project/bios_config/manager", -+ std::array<const char*, 0>()); -+ } -+}; ++ "xyz.openbmc_project.ObjectMapper", ++ "/xyz/openbmc_project/object_mapper", ++ "xyz.openbmc_project.ObjectMapper", "GetObject", ++ "/xyz/openbmc_project/bios_config/manager", ++ std::array<const char*, 0>()); + }); + } + +/** + * BiosSettings class supports handle GET/PATCH method for + * BIOS configuration pending settings. + */ -+class BiosSettings : public Node ++inline void requestRoutesBiosSettings(App& app) +{ -+ public: -+ BiosSettings(App& app) : -+ Node(app, "/redfish/v1/Systems/system/Bios/Settings") -+ { -+ entityPrivileges = {{boost::beast::http::verb::get, {{"Login"}}}}; -+ } -+ -+ 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/Settings"; -+ asyncResp->res.jsonValue["@odata.type"] = "#Bios.v1_1_0.Bios"; -+ asyncResp->res.jsonValue["Name"] = "Bios Settings Version 1"; -+ asyncResp->res.jsonValue["Id"] = "BiosSettingsV1"; -+ asyncResp->res.jsonValue["AttributeRegistry"] = "BiosAttributeRegistry"; -+ asyncResp->res.jsonValue["Attributes"] = {}; -+ -+ crow::connections::systemBus->async_method_call( -+ [asyncResp](const boost::system::error_code ec, -+ const GetObjectType& getObjectType) { -+ if (ec) -+ { -+ BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " -+ << ec; -+ messages::internalError(asyncResp->res); -+ -+ return; -+ } -+ std::string service = getObjectType.begin()->first; ++ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Bios/Settings") ++ .privileges(redfish::privileges::getBios) ++ .methods(boost::beast::http::verb::get)( ++ [](const crow::Request&, ++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { ++ asyncResp->res.jsonValue["@odata.id"] = ++ asyncResp->res.jsonValue["@odata.id"] = ++ "/redfish/v1/Systems/system/Bios/Settings"; ++ asyncResp->res.jsonValue["@odata.type"] = "#Bios.v1_1_0.Bios"; ++ asyncResp->res.jsonValue["Name"] = "Bios Settings Version 1"; ++ asyncResp->res.jsonValue["Id"] = "BiosSettingsV1"; ++ asyncResp->res.jsonValue["AttributeRegistry"] = ++ "BiosAttributeRegistry"; ++ asyncResp->res.jsonValue["Attributes"] = {}; + + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec, -+ const std::variant<PendingAttributesType>& -+ retPendingAttributes) { ++ const GetObjectType& getObjectType) { + if (ec) + { -+ BMCWEB_LOG_ERROR << "getBiosSettings DBUS error: " -+ << ec; -+ messages::resourceNotFound(asyncResp->res, -+ "Systems/system/Bios", -+ "Settings"); -+ return; -+ } -+ const PendingAttributesType* pendingAttributes = -+ std::get_if<PendingAttributesType>( -+ &retPendingAttributes); -+ nlohmann::json& attributesJson = -+ asyncResp->res.jsonValue["Attributes"]; -+ if (pendingAttributes == nullptr) -+ { -+ BMCWEB_LOG_ERROR << "pendingAttributes == nullptr "; ++ BMCWEB_LOG_ERROR ++ << "ObjectMapper::GetObject call failed: " ++ << ec; + messages::internalError(asyncResp->res); ++ + return; + } -+ for (const PendingAttributesItemType& item : -+ *pendingAttributes) -+ { -+ const std::string& key = item.first; -+ const std::string& itemType = -+ std::get<pendingAttrType>(item.second); -+ std::string attrType = -+ mapAttrTypeToRedfish(itemType); -+ if (attrType == "String") -+ { -+ const std::string* currValue = -+ std::get_if<std::string>( -+ &std::get<pendingAttrValue>( -+ item.second)); -+ attributesJson.emplace(key, currValue != nullptr -+ ? *currValue -+ : ""); -+ } -+ else if (attrType == "Integer") -+ { -+ const int64_t* currValue = std::get_if<int64_t>( -+ &std::get<pendingAttrValue>(item.second)); -+ attributesJson.emplace( -+ key, currValue != nullptr ? *currValue : 0); -+ } -+ else -+ { -+ BMCWEB_LOG_ERROR -+ << "Unsupported attribute type."; -+ messages::internalError(asyncResp->res); -+ } -+ } ++ std::string service = getObjectType.begin()->first; ++ ++ crow::connections::systemBus->async_method_call( ++ [asyncResp]( ++ const boost::system::error_code ec, ++ const std::variant<PendingAttributesType>& ++ retPendingAttributes) { ++ if (ec) ++ { ++ BMCWEB_LOG_ERROR ++ << "getBiosSettings DBUS error: " << ec; ++ messages::resourceNotFound( ++ asyncResp->res, "Systems/system/Bios", ++ "Settings"); ++ return; ++ } ++ const PendingAttributesType* pendingAttributes = ++ std::get_if<PendingAttributesType>( ++ &retPendingAttributes); ++ nlohmann::json& attributesJson = ++ asyncResp->res.jsonValue["Attributes"]; ++ if (pendingAttributes == nullptr) ++ { ++ BMCWEB_LOG_ERROR ++ << "pendingAttributes == nullptr "; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ for (const PendingAttributesItemType& item : ++ *pendingAttributes) ++ { ++ const std::string& key = item.first; ++ const std::string& itemType = ++ std::get<pendingAttrType>(item.second); ++ std::string attrType = ++ mapAttrTypeToRedfish(itemType); ++ if (attrType == "String") ++ { ++ const std::string* currValue = ++ std::get_if<std::string>( ++ &std::get<pendingAttrValue>( ++ item.second)); ++ attributesJson.emplace( ++ key, currValue != nullptr ++ ? *currValue ++ : ""); ++ } ++ else if (attrType == "Integer") ++ { ++ const int64_t* currValue = ++ std::get_if<int64_t>( ++ &std::get<pendingAttrValue>( ++ item.second)); ++ attributesJson.emplace( ++ key, currValue != nullptr ++ ? *currValue ++ : 0); ++ } ++ else ++ { ++ BMCWEB_LOG_ERROR ++ << "Unsupported attribute type."; ++ messages::internalError(asyncResp->res); ++ } ++ } ++ }, ++ service, "/xyz/openbmc_project/bios_config/manager", ++ "org.freedesktop.DBus.Properties", "Get", ++ "xyz.openbmc_project.BIOSConfig.Manager", ++ "PendingAttributes"); + }, -+ service, "/xyz/openbmc_project/bios_config/manager", -+ "org.freedesktop.DBus.Properties", "Get", -+ "xyz.openbmc_project.BIOSConfig.Manager", -+ "PendingAttributes"); -+ }, -+ "xyz.openbmc_project.ObjectMapper", -+ "/xyz/openbmc_project/object_mapper", -+ "xyz.openbmc_project.ObjectMapper", "GetObject", -+ "/xyz/openbmc_project/bios_config/manager", -+ std::array<const char*, 0>()); -+ } -+}; ++ "xyz.openbmc_project.ObjectMapper", ++ "/xyz/openbmc_project/object_mapper", ++ "xyz.openbmc_project.ObjectMapper", "GetObject", ++ "/xyz/openbmc_project/bios_config/manager", ++ std::array<const char*, 0>()); ++ }); ++} +/** + * BiosAttributeRegistry class supports handle get method for BIOS attribute + * registry. + */ -+class BiosAttributeRegistry : public Node ++inline void requestRoutesBiosAttributeRegistry(App& app) +{ -+ public: -+ BiosAttributeRegistry(App& app) : -+ Node(app, "/redfish/v1/Registries/BiosAttributeRegistry/" -+ "BiosAttributeRegistry") -+ { -+ entityPrivileges = {{boost::beast::http::verb::get, {{"Login"}}}}; -+ } -+ -+ 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/Registries/BiosAttributeRegistry/" -+ "BiosAttributeRegistry"; -+ asyncResp->res.jsonValue["@odata.type"] = -+ "#AttributeRegistry.v1_3_2.AttributeRegistry"; -+ asyncResp->res.jsonValue["Name"] = "Bios Attribute Registry"; -+ asyncResp->res.jsonValue["Id"] = "BiosAttributeRegistry"; -+ asyncResp->res.jsonValue["RegistryVersion"] = "1.0.0"; -+ asyncResp->res.jsonValue["Language"] = "en"; -+ asyncResp->res.jsonValue["OwningEntity"] = "OpenBMC"; -+ asyncResp->res.jsonValue["RegistryEntries"]["Attributes"] = -+ nlohmann::json::array(); ++ BMCWEB_ROUTE( ++ app, ++ "/redfish/v1/Registries/BiosAttributeRegistry/BiosAttributeRegistry/") ++ .privileges(redfish::privileges::getBios) ++ .methods( ++ boost::beast::http::verb:: ++ get)([](const crow::Request&, ++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { ++ asyncResp->res.jsonValue["@odata.id"] = ++ "/redfish/v1/Registries/BiosAttributeRegistry/" ++ "BiosAttributeRegistry"; ++ asyncResp->res.jsonValue["@odata.type"] = ++ "#AttributeRegistry.v1_3_2.AttributeRegistry"; ++ asyncResp->res.jsonValue["Name"] = "Bios Attribute Registry"; ++ asyncResp->res.jsonValue["Id"] = "BiosAttributeRegistry"; ++ asyncResp->res.jsonValue["RegistryVersion"] = "1.0.0"; ++ asyncResp->res.jsonValue["Language"] = "en"; ++ asyncResp->res.jsonValue["OwningEntity"] = "OpenBMC"; ++ asyncResp->res.jsonValue["RegistryEntries"]["Attributes"] = ++ nlohmann::json::array(); + -+ crow::connections::systemBus->async_method_call( -+ [asyncResp](const boost::system::error_code ec, -+ const GetObjectType& getObjectType) { -+ if (ec) -+ { -+ BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " -+ << ec; -+ messages::internalError(asyncResp->res); ++ crow::connections::systemBus->async_method_call( ++ [asyncResp](const boost::system::error_code ec, ++ const GetObjectType& getObjectType) { ++ if (ec) ++ { ++ BMCWEB_LOG_ERROR ++ << "ObjectMapper::GetObject call failed: " << ec; ++ messages::internalError(asyncResp->res); + -+ return; -+ } -+ std::string service = getObjectType.begin()->first; ++ return; ++ } ++ std::string service = getObjectType.begin()->first; + -+ crow::connections::systemBus->async_method_call( -+ [asyncResp]( -+ const boost::system::error_code ec, -+ const std::variant<BiosBaseTableType>& retBiosTable) { -+ if (ec) -+ { -+ BMCWEB_LOG_ERROR -+ << "getBiosAttributeRegistry DBUS error: " -+ << ec; -+ messages::resourceNotFound( -+ asyncResp->res, "Registries/Bios", "Bios"); -+ return; -+ } -+ const BiosBaseTableType* baseBiosTable = -+ std::get_if<BiosBaseTableType>(&retBiosTable); -+ nlohmann::json& attributeArray = -+ asyncResp->res -+ .jsonValue["RegistryEntries"]["Attributes"]; -+ nlohmann::json optionsArray = nlohmann::json::array(); -+ if (baseBiosTable == nullptr) -+ { -+ BMCWEB_LOG_ERROR << "baseBiosTable == nullptr "; -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ for (const BiosBaseTableItemType& item : *baseBiosTable) -+ { -+ const std::string& itemType = -+ std::get<biosBaseAttrType>(item.second); -+ std::string attrType = -+ mapAttrTypeToRedfish(itemType); -+ if (attrType == "UNKNOWN") ++ crow::connections::systemBus->async_method_call( ++ [asyncResp](const boost::system::error_code ec, ++ const std::variant<BiosBaseTableType>& ++ retBiosTable) { ++ if (ec) + { -+ BMCWEB_LOG_ERROR << "attrType == UNKNOWN"; -+ messages::internalError(asyncResp->res); ++ BMCWEB_LOG_ERROR ++ << "getBiosAttributeRegistry DBUS error: " ++ << ec; ++ messages::resourceNotFound( ++ asyncResp->res, "Registries/Bios", "Bios"); + return; + } -+ nlohmann::json attributeItem; -+ attributeItem["AttributeName"] = item.first; -+ attributeItem["Type"] = attrType; -+ attributeItem["ReadOnly"] = -+ std::get<biosBaseReadonlyStatus>(item.second); -+ attributeItem["DisplayName"] = -+ std::get<biosBaseDisplayName>(item.second); -+ attributeItem["HelpText"] = -+ std::get<biosBaseDescription>(item.second); -+ attributeItem["MenuPath"] = -+ std::get<biosBaseMenuPath>(item.second); -+ -+ if (attrType == "String") -+ { -+ const std::string* currValue = -+ std::get_if<std::string>( -+ &std::get<biosBaseCurrValue>( -+ item.second)); -+ const std::string* defValue = -+ std::get_if<std::string>( -+ &std::get<biosBaseDefaultValue>( -+ item.second)); -+ attributeItem["CurrentValue"] = -+ currValue != nullptr ? *currValue : ""; -+ attributeItem["DefaultValue"] = -+ defValue != nullptr ? *defValue : ""; -+ } -+ else if (attrType == "Integer") -+ { -+ const int64_t* currValue = std::get_if<int64_t>( -+ &std::get<biosBaseCurrValue>(item.second)); -+ const int64_t* defValue = std::get_if<int64_t>( -+ &std::get<biosBaseDefaultValue>( -+ item.second)); -+ attributeItem["CurrentValue"] = -+ currValue != nullptr ? *currValue : 0; -+ attributeItem["DefaultValue"] = -+ defValue != nullptr ? *defValue : 0; -+ } -+ else ++ const BiosBaseTableType* baseBiosTable = ++ std::get_if<BiosBaseTableType>(&retBiosTable); ++ nlohmann::json& attributeArray = ++ asyncResp->res ++ .jsonValue["RegistryEntries"]["Attributes"]; ++ nlohmann::json optionsArray = ++ nlohmann::json::array(); ++ if (baseBiosTable == nullptr) + { -+ BMCWEB_LOG_ERROR -+ << "Unsupported attribute type."; ++ BMCWEB_LOG_ERROR << "baseBiosTable == nullptr "; + messages::internalError(asyncResp->res); + return; + } -+ -+ const std::vector<OptionsItemType>& optionsVector = -+ std::get<biosBaseOptions>(item.second); -+ for (const OptionsItemType& optItem : optionsVector) ++ for (const BiosBaseTableItemType& item : ++ *baseBiosTable) + { -+ nlohmann::json optItemJson; -+ const std::string& strOptItemType = -+ std::get<optItemType>(optItem); -+ std::string optItemTypeRedfish = -+ mapBoundTypeToRedfish(strOptItemType); -+ if (optItemTypeRedfish == "UNKNOWN") ++ const std::string& itemType = ++ std::get<biosBaseAttrType>(item.second); ++ std::string attrType = ++ mapAttrTypeToRedfish(itemType); ++ if (attrType == "UNKNOWN") + { -+ BMCWEB_LOG_ERROR -+ << "optItemTypeRedfish == UNKNOWN"; ++ BMCWEB_LOG_ERROR << "attrType == UNKNOWN"; + messages::internalError(asyncResp->res); + return; + } -+ if (optItemTypeRedfish == "OneOf") ++ nlohmann::json attributeItem; ++ attributeItem["AttributeName"] = item.first; ++ attributeItem["Type"] = attrType; ++ attributeItem["ReadOnly"] = ++ std::get<biosBaseReadonlyStatus>( ++ item.second); ++ attributeItem["DisplayName"] = ++ std::get<biosBaseDisplayName>(item.second); ++ attributeItem["HelpText"] = ++ std::get<biosBaseDescription>(item.second); ++ attributeItem["MenuPath"] = ++ std::get<biosBaseMenuPath>(item.second); ++ ++ if (attrType == "String") + { + const std::string* currValue = + std::get_if<std::string>( -+ &std::get<optItemValue>(optItem)); -+ optItemJson[optItemTypeRedfish] = ++ &std::get<biosBaseCurrValue>( ++ item.second)); ++ const std::string* defValue = ++ std::get_if<std::string>( ++ &std::get<biosBaseDefaultValue>( ++ item.second)); ++ attributeItem["CurrentValue"] = + currValue != nullptr ? *currValue : ""; ++ attributeItem["DefaultValue"] = ++ defValue != nullptr ? *defValue : ""; + } -+ else ++ else if (attrType == "Integer") + { + const int64_t* currValue = + std::get_if<int64_t>( -+ &std::get<optItemValue>(optItem)); -+ optItemJson[optItemTypeRedfish] = ++ &std::get<biosBaseCurrValue>( ++ item.second)); ++ const int64_t* defValue = ++ std::get_if<int64_t>( ++ &std::get<biosBaseDefaultValue>( ++ item.second)); ++ attributeItem["CurrentValue"] = + currValue != nullptr ? *currValue : 0; ++ attributeItem["DefaultValue"] = ++ defValue != nullptr ? *defValue : 0; ++ } ++ else ++ { ++ BMCWEB_LOG_ERROR ++ << "Unsupported attribute type."; ++ messages::internalError(asyncResp->res); ++ return; + } + -+ optionsArray.push_back(optItemJson); -+ } ++ const std::vector<OptionsItemType>& ++ optionsVector = ++ std::get<biosBaseOptions>(item.second); ++ for (const OptionsItemType& optItem : ++ optionsVector) ++ { ++ nlohmann::json optItemJson; ++ const std::string& strOptItemType = ++ std::get<optItemType>(optItem); ++ std::string optItemTypeRedfish = ++ mapBoundTypeToRedfish(strOptItemType); ++ if (optItemTypeRedfish == "UNKNOWN") ++ { ++ BMCWEB_LOG_ERROR ++ << "optItemTypeRedfish == UNKNOWN"; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ if (optItemTypeRedfish == "OneOf") ++ { ++ const std::string* currValue = ++ std::get_if<std::string>( ++ &std::get<optItemValue>( ++ optItem)); ++ optItemJson[optItemTypeRedfish] = ++ currValue != nullptr ? *currValue ++ : ""; ++ } ++ else ++ { ++ const int64_t* currValue = ++ std::get_if<int64_t>( ++ &std::get<optItemValue>( ++ optItem)); ++ optItemJson[optItemTypeRedfish] = ++ currValue != nullptr ? *currValue ++ : 0; ++ } + -+ attributeItem["Value"] = optionsArray; -+ attributeArray.push_back(attributeItem); -+ } -+ }, -+ service, "/xyz/openbmc_project/bios_config/manager", -+ "org.freedesktop.DBus.Properties", "Get", -+ "xyz.openbmc_project.BIOSConfig.Manager", "BaseBIOSTable"); -+ }, -+ "xyz.openbmc_project.ObjectMapper", -+ "/xyz/openbmc_project/object_mapper", -+ "xyz.openbmc_project.ObjectMapper", "GetObject", -+ "/xyz/openbmc_project/bios_config/manager", -+ std::array<const char*, 0>()); - } - }; ++ optionsArray.push_back(optItemJson); ++ } ++ ++ attributeItem["Value"] = optionsArray; ++ attributeArray.push_back(attributeItem); ++ } ++ }, ++ service, "/xyz/openbmc_project/bios_config/manager", ++ "org.freedesktop.DBus.Properties", "Get", ++ "xyz.openbmc_project.BIOSConfig.Manager", ++ "BaseBIOSTable"); ++ }, ++ "xyz.openbmc_project.ObjectMapper", ++ "/xyz/openbmc_project/object_mapper", ++ "xyz.openbmc_project.ObjectMapper", "GetObject", ++ "/xyz/openbmc_project/bios_config/manager", ++ std::array<const char*, 0>()); ++ }); ++} /** + * BiosReset class supports handle POST method for Reset bios. + * The class retrieves and sends data directly to D-Bus. diff --git a/redfish-core/lib/message_registries.hpp b/redfish-core/lib/message_registries.hpp -index 455bf70..7afbfc2 100644 +index e3bd5bf..f1f130a 100644 --- a/redfish-core/lib/message_registries.hpp +++ b/redfish-core/lib/message_registries.hpp -@@ -18,6 +18,7 @@ - #include "node.hpp" +@@ -17,6 +17,7 @@ + #include "registries.hpp" #include "registries/base_message_registry.hpp" +#include "registries/bios_registry.hpp" #include "registries/openbmc_message_registry.hpp" #include "registries/resource_event_message_registry.hpp" #include "registries/task_event_message_registry.hpp" -@@ -56,11 +57,12 @@ class MessageRegistryFileCollection : public Node - {"@odata.id", "/redfish/v1/Registries"}, - {"Name", "MessageRegistryFile Collection"}, - {"Description", "Collection of MessageRegistryFiles"}, -- {"Members@odata.count", 4}, -+ {"Members@odata.count", 5}, - {"Members", - {{{"@odata.id", "/redfish/v1/Registries/Base"}}, - {{"@odata.id", "/redfish/v1/Registries/TaskEvent"}}, - {{"@odata.id", "/redfish/v1/Registries/ResourceEvent"}}, -+ {{"@odata.id", "/redfish/v1/Registries/BiosAttributeRegistry"}}, - {{"@odata.id", "/redfish/v1/Registries/OpenBMC"}}}}}; - } - }; -@@ -116,6 +118,11 @@ class MessageRegistryFile : public Node - header = &message_registries::resource_event::header; - url = message_registries::resource_event::url; - } -+ else if (registry == "BiosAttributeRegistry") -+ { -+ header = &message_registries::bios::header; -+ dmtf.clear(); -+ } - else - { - messages::resourceNotFound( +@@ -87,6 +88,11 @@ inline void requestRoutesMessageRegistryFile(App& app) + header = &message_registries::resource_event::header; + url = message_registries::resource_event::url; + } ++ else if (registry == "BiosAttributeRegistry") ++ { ++ header = &message_registries::bios::header; ++ dmtf.clear(); ++ } + else + { + messages::resourceNotFound( -- 2.17.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0002-BaseBiosTable-Add-support-for-PATCH-operation.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0002-BaseBiosTable-Add-support-for-PATCH-operation.patch index 21a21e8db..099e6ddf5 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0002-BaseBiosTable-Add-support-for-PATCH-operation.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0002-BaseBiosTable-Add-support-for-PATCH-operation.patch @@ -1,7 +1,7 @@ -From 9c498d683be59ce25dd0124ba7ec5e026c59bbbf Mon Sep 17 00:00:00 2001 -From: Kuiying Wang <kuiying.wang@intel.com> -Date: Wed, 23 Dec 2020 16:50:45 +0800 -Subject: [PATCH] BaseBiosTable: Add support for PATCH operation +From ffa924ef204930a5bb442bf654eac02543acfb8f Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> +Date: Wed, 30 Jun 2021 15:18:46 +0000 +Subject: [PATCH 2/5] BaseBiosTable: Add support for PATCH operation This commit brings in support for PATCH operation of the bios variables that updates the BaseBiosTable. @@ -25,12 +25,13 @@ This makes use of the "Set" of "PendingAttributes" in the backend and that updates the BaseBiosTable. Signed-off-by: Kuiying Wang <kuiying.wang@intel.com> +Change-Id: I12e78e5ac623c264c7a3e1dd5198aca67172736d --- - redfish-core/lib/bios.hpp | 93 ++++++++++++++++++++++++++++++++++++++- - 1 file changed, 92 insertions(+), 1 deletion(-) + redfish-core/lib/bios.hpp | 95 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 95 insertions(+) diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp -index cb2b74d..860a643 100644 +index c1a5c56..14d2171 100644 --- a/redfish-core/lib/bios.hpp +++ b/redfish-core/lib/bios.hpp @@ -96,6 +96,29 @@ static std::string mapAttrTypeToRedfish(const std::string_view typeDbus) @@ -63,88 +64,83 @@ index cb2b74d..860a643 100644 static std::string mapBoundTypeToRedfish(const std::string_view typeDbus) { std::string ret; -@@ -260,7 +283,9 @@ class BiosSettings : public Node - BiosSettings(App& app) : - Node(app, "/redfish/v1/Systems/system/Bios/Settings") - { -- entityPrivileges = {{boost::beast::http::verb::get, {{"Login"}}}}; -+ entityPrivileges = { -+ {boost::beast::http::verb::get, {{"Login"}}}, -+ {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}}; - } - - private: -@@ -356,6 +381,72 @@ class BiosSettings : public Node - "/xyz/openbmc_project/bios_config/manager", - std::array<const char*, 0>()); - } -+ -+ void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, -+ const crow::Request& req, -+ const std::vector<std::string>&) override -+ { -+ nlohmann::json inpJson; +@@ -370,6 +393,78 @@ inline void requestRoutesBiosSettings(App& app) + "/xyz/openbmc_project/bios_config/manager", + std::array<const char*, 0>()); + }); + -+ if (!redfish::json_util::readJson(req, asyncResp->res, "data", inpJson)) -+ { -+ return; -+ } ++ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Bios/Settings") ++ .privileges({{"ConfigureComponents"}}) ++ .methods(boost::beast::http::verb::patch)( ++ [](const crow::Request& req, ++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { ++ nlohmann::json inpJson; + -+ for (auto& attrInfo : inpJson) -+ { -+ std::optional<std::string> attrName; -+ std::optional<std::string> attrType; -+ std::optional<std::string> attrValue; -+ if (!json_util::getValueFromJsonObject(attrInfo, "AttributeName", -+ attrName)) -+ { -+ messages::propertyMissing(asyncResp->res, "AttributeName"); -+ return; -+ } -+ if (!json_util::getValueFromJsonObject(attrInfo, "AttributeType", -+ attrType)) -+ { -+ messages::propertyMissing(asyncResp->res, "AttributeType"); -+ return; -+ } -+ if (!json_util::getValueFromJsonObject(attrInfo, "AttributeValue", -+ attrValue)) -+ { -+ messages::propertyMissing(asyncResp->res, "AttributeValue"); -+ return; -+ } -+ std::string biosAttrType = mapRedfishToAttrType(*attrType); ++ if (!redfish::json_util::readJson(req, asyncResp->res, "data", ++ inpJson)) ++ { ++ return; ++ } + -+ if (biosAttrType == "UNKNOWN") -+ { -+ BMCWEB_LOG_ERROR << "Invalid attribute type"; -+ messages::propertyValueNotInList(asyncResp->res, -+ "AttributeType", *attrType); -+ return; -+ } -+ -+ PendingAttributesType pendingAttributes; -+ pendingAttributes.emplace_back(std::make_pair( -+ *attrName, std::make_tuple(biosAttrType, *attrValue))); ++ for (auto& attrInfo : inpJson) ++ { ++ std::optional<std::string> attrName; ++ std::optional<std::string> attrType; ++ std::optional<std::string> attrValue; ++ if (!json_util::getValueFromJsonObject( ++ attrInfo, "AttributeName", attrName)) ++ { ++ messages::propertyMissing(asyncResp->res, ++ "AttributeName"); ++ return; ++ } ++ if (!json_util::getValueFromJsonObject( ++ attrInfo, "AttributeType", attrType)) ++ { ++ messages::propertyMissing(asyncResp->res, ++ "AttributeType"); ++ return; ++ } ++ if (!json_util::getValueFromJsonObject( ++ attrInfo, "AttributeValue", attrValue)) ++ { ++ messages::propertyMissing(asyncResp->res, ++ "AttributeValue"); ++ return; ++ } ++ std::string biosAttrType = mapRedfishToAttrType(*attrType); + -+ crow::connections::systemBus->async_method_call( -+ [asyncResp](const boost::system::error_code ec) { -+ if (ec) ++ if (biosAttrType == "UNKNOWN") + { -+ BMCWEB_LOG_ERROR << "doPatch resp_handler got error " -+ << ec; -+ messages::internalError(asyncResp->res); ++ BMCWEB_LOG_ERROR << "Invalid attribute type"; ++ messages::propertyValueNotInList( ++ asyncResp->res, "AttributeType", *attrType); + return; + } -+ }, -+ "xyz.openbmc_project.BIOSConfigManager", -+ "/xyz/openbmc_project/bios_config/manager", -+ "org.freedesktop.DBus.Properties", "Set", -+ "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes", -+ std::variant<PendingAttributesType>(pendingAttributes)); -+ } -+ } - }; ++ ++ PendingAttributesType pendingAttributes; ++ pendingAttributes.emplace_back(std::make_pair( ++ *attrName, std::make_tuple(biosAttrType, *attrValue))); ++ ++ crow::connections::systemBus->async_method_call( ++ [asyncResp](const boost::system::error_code ec) { ++ if (ec) ++ { ++ BMCWEB_LOG_ERROR ++ << "doPatch resp_handler got error " << ec; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ }, ++ "xyz.openbmc_project.BIOSConfigManager", ++ "/xyz/openbmc_project/bios_config/manager", ++ "org.freedesktop.DBus.Properties", "Set", ++ "xyz.openbmc_project.BIOSConfig.Manager", ++ "PendingAttributes", ++ std::variant<PendingAttributesType>(pendingAttributes)); ++ } ++ }); + } /** * BiosAttributeRegistry class supports handle get method for BIOS attribute -- diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0003-Add-support-to-ResetBios-action.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0003-Add-support-to-ResetBios-action.patch index 5a24996a0..028d09e74 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0003-Add-support-to-ResetBios-action.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0003-Add-support-to-ResetBios-action.patch @@ -1,7 +1,7 @@ -From 4e85ce8a5f34038c289504855d21ebfa3d6b94f0 Mon Sep 17 00:00:00 2001 -From: Kuiying Wang <kuiying.wang@intel.com> -Date: Wed, 23 Dec 2020 22:47:56 +0800 -Subject: [PATCH] Add support to ResetBios action +From 02e44acef17a2b0681fe019e090d09015f9412e0 Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> +Date: Wed, 30 Jun 2021 15:27:16 +0000 +Subject: [PATCH 3/5] Add support to ResetBios action Tested: @@ -11,50 +11,48 @@ POST https://IP_ADDR/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios Change-Id: I5e5fbdd70d4a3ce3b976cc2eb0a7d9a2a3adb124 Signed-off-by: Kuiying Wang <kuiying.wang@intel.com> --- - redfish-core/lib/bios.hpp | 15 ++++++++++----- - 1 file changed, 10 insertions(+), 5 deletions(-) + redfish-core/lib/bios.hpp | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp -index 860a643..1eb7bef 100644 +index 14d2171..49c0fd0 100644 --- a/redfish-core/lib/bios.hpp +++ b/redfish-core/lib/bios.hpp -@@ -638,7 +638,7 @@ class BiosReset : public Node - Node(app, "/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios/") - { - entityPrivileges = { -- {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; -+ {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; - } - - private: -@@ -649,19 +649,24 @@ class BiosReset : public Node - void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const crow::Request&, const std::vector<std::string>&) override - { -+ std::string resetFlag = -+ "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag.FactoryDefaults"; - - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec) { - if (ec) - { -- BMCWEB_LOG_ERROR << "Failed to reset bios: " << ec; -+ BMCWEB_LOG_ERROR << "doPost bios reset got error " << ec; - messages::internalError(asyncResp->res); - return; - } -+ BMCWEB_LOG_DEBUG << "bios reset action is done"; - }, -- "org.open_power.Software.Host.Updater", -- "/xyz/openbmc_project/software", -- "xyz.openbmc_project.Common.FactoryReset", "Reset"); -+ "xyz.openbmc_project.BIOSConfigManager", -+ "/xyz/openbmc_project/bios_config/manager", -+ "org.freedesktop.DBus.Properties", "Set", -+ "xyz.openbmc_project.BIOSConfig.Manager", "ResetBIOSSettings", -+ std::variant<std::string>(resetFlag)); - } - }; +@@ -665,24 +665,28 @@ inline void requestRoutesBiosAttributeRegistry(App& app) + inline void requestRoutesBiosReset(App& app) + { + BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios/") +- // Incorrect Privilege; Should be ConfigureComponents +- //.privileges(redfish::privileges::postBios) +- .privileges({{"ConfigureManager"}}) ++ .privileges(redfish::privileges::postBios) + .methods(boost::beast::http::verb::post)( + [](const crow::Request&, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { ++ std::string resetFlag = "xyz.openbmc_project.BIOSConfig." ++ "Manager.ResetFlag.FactoryDefaults"; ++ + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec) { + if (ec) + { +- BMCWEB_LOG_ERROR << "Failed to reset bios: " << ec; ++ BMCWEB_LOG_ERROR << "doPost bios reset got error " ++ << ec; + messages::internalError(asyncResp->res); + return; + } + }, +- "org.open_power.Software.Host.Updater", +- "/xyz/openbmc_project/software", +- "xyz.openbmc_project.Common.FactoryReset", "Reset"); ++ "xyz.openbmc_project.BIOSConfigManager", ++ "/xyz/openbmc_project/bios_config/manager", ++ "org.freedesktop.DBus.Properties", "Set", ++ "xyz.openbmc_project.BIOSConfig.Manager", ++ "ResetBIOSSettings", std::variant<std::string>(resetFlag)); + }); + } } // namespace redfish -- 2.17.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0004-Add-support-to-ChangePassword-action.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0004-Add-support-to-ChangePassword-action.patch index e87995aca..9a2fada9e 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0004-Add-support-to-ChangePassword-action.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0004-Add-support-to-ChangePassword-action.patch @@ -1,7 +1,7 @@ -From 0ce94f6caf5d76d7f1abc71f6f8f7dc320517984 Mon Sep 17 00:00:00 2001 -From: Kuiying Wang <kuiying.wang@intel.com> -Date: Wed, 23 Dec 2020 14:41:23 +0800 -Subject: [PATCH] Add support to ChangePassword action +From 34f8680b21a134e2133bdcf41e1e83e4b4a05d28 Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> +Date: Wed, 30 Jun 2021 15:37:47 +0000 +Subject: [PATCH 4/5] Add support to ChangePassword action Tested: @@ -32,108 +32,85 @@ root@intel-obmc:~# cat /var/lib/bios-settings-manager/passwordData Change-Id: I90319a68da0b0a7f9c5cd65a8cb8cf52269a5f52 Signed-off-by: Kuiying Wang <kuiying.wang@intel.com> --- - redfish-core/include/redfish.hpp | 1 + - redfish-core/lib/bios.hpp | 70 ++++++++++++++++++++++++++++++++ - 2 files changed, 71 insertions(+) + redfish-core/lib/bios.hpp | 58 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 58 insertions(+) -diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp -index 298ebb8..4418c3d 100644 ---- a/redfish-core/include/redfish.hpp -+++ b/redfish-core/include/redfish.hpp -@@ -159,6 +159,7 @@ class RedfishService - nodes.emplace_back(std::make_unique<BiosSettings>(app)); - nodes.emplace_back(std::make_unique<BiosAttributeRegistry>(app)); - nodes.emplace_back(std::make_unique<BiosReset>(app)); -+ nodes.emplace_back(std::make_unique<BiosChangePassword>(app)); - #ifdef BMCWEB_ENABLE_VM_NBDPROXY - nodes.emplace_back(std::make_unique<VirtualMedia>(app)); - nodes.emplace_back(std::make_unique<VirtualMediaCollection>(app)); diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp -index 1eb7bef..12ec472 100644 +index 49c0fd0..0250c59 100644 --- a/redfish-core/lib/bios.hpp +++ b/redfish-core/lib/bios.hpp -@@ -184,6 +184,9 @@ class BiosService : public Node - asyncResp->res.jsonValue["Actions"]["#Bios.ResetBios"] = { - {"target", - "/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios"}}; -+ asyncResp->res.jsonValue["Actions"]["#Bios.ChangePassword"] = { -+ {"target", -+ "/redfish/v1/Systems/system/Bios/Actions/Bios.ChangePassword"}}; +@@ -180,6 +180,9 @@ inline void requestRoutesBiosService(App& app) + asyncResp->res.jsonValue["Actions"]["#Bios.ResetBios"] = { + {"target", + "/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios"}}; ++ asyncResp->res.jsonValue["Actions"]["#Bios.ChangePassword"] = { ++ {"target", "/redfish/v1/Systems/system/Bios/Actions/" ++ "Bios.ChangePassword"}}; + + // Get the ActiveSoftwareImage and SoftwareImages + fw_util::populateFirmwareInformation( +@@ -283,6 +286,61 @@ inline void requestRoutesBiosService(App& app) + }); + } - // Get the ActiveSoftwareImage and SoftwareImages - fw_util::populateFirmwareInformation(asyncResp, fw_util::biosPurpose, -@@ -669,4 +672,71 @@ class BiosReset : public Node - std::variant<std::string>(resetFlag)); - } - }; -+ +/** + * BiosChangePassword class supports handle POST method for change bios + * password. The class retrieves and sends data directly to D-Bus. + */ -+class BiosChangePassword : public Node ++inline void requestRoutesBiosChangePassword(App& app) +{ -+ public: -+ BiosChangePassword(App& app) : -+ Node(app, -+ "/redfish/v1/Systems/system/Bios/Actions/Bios.ChangePassword/") -+ { -+ 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::string currentPassword, newPassword, userName; -+ if (!json_util::readJson(req, asyncResp->res, "NewPassword", -+ newPassword, "OldPassword", currentPassword, -+ "PasswordName", userName)) -+ { -+ return; -+ } -+ if (currentPassword.empty()) -+ { -+ messages::actionParameterUnknown(asyncResp->res, "ChangePassword", -+ "OldPassword"); -+ return; -+ } -+ if (newPassword.empty()) -+ { -+ messages::actionParameterUnknown(asyncResp->res, "ChangePassword", -+ "NewPassword"); -+ return; -+ } -+ if (userName.empty()) -+ { -+ messages::actionParameterUnknown(asyncResp->res, "ChangePassword", -+ "PasswordName"); -+ return; -+ } -+ crow::connections::systemBus->async_method_call( -+ [asyncResp](const boost::system::error_code ec) { -+ if (ec) ++ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Bios/") ++ .privileges({{"ConfigureComponents"}}) ++ .methods(boost::beast::http::verb::post)( ++ [](const crow::Request& req, ++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { ++ std::string currentPassword, newPassword, userName; ++ if (!json_util::readJson(req, asyncResp->res, "NewPassword", ++ newPassword, "OldPassword", ++ currentPassword, "PasswordName", ++ userName)) ++ { ++ return; ++ } ++ if (currentPassword.empty()) ++ { ++ messages::actionParameterUnknown( ++ asyncResp->res, "ChangePassword", "OldPassword"); ++ return; ++ } ++ if (newPassword.empty()) ++ { ++ messages::actionParameterUnknown( ++ asyncResp->res, "ChangePassword", "NewPassword"); ++ return; ++ } ++ if (userName.empty()) + { -+ BMCWEB_LOG_CRITICAL -+ << "Failed in doPost(BiosChangePassword) " << ec; -+ messages::internalError(asyncResp->res); ++ messages::actionParameterUnknown( ++ asyncResp->res, "ChangePassword", "PasswordName"); + return; + } -+ }, -+ "xyz.openbmc_project.BIOSConfigPassword", -+ "/xyz/openbmc_project/bios_config/password", -+ "xyz.openbmc_project.BIOSConfig.Password", "ChangePassword", -+ userName, currentPassword, newPassword); -+ } -+}; ++ crow::connections::systemBus->async_method_call( ++ [asyncResp](const boost::system::error_code ec) { ++ if (ec) ++ { ++ BMCWEB_LOG_CRITICAL ++ << "Failed in doPost(BiosChangePassword) " ++ << ec; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ }, ++ "xyz.openbmc_project.BIOSConfigPassword", ++ "/xyz/openbmc_project/bios_config/password", ++ "xyz.openbmc_project.BIOSConfig.Password", "ChangePassword", ++ userName, currentPassword, newPassword); ++ }); ++} + - } // namespace redfish + /** + * BiosSettings class supports handle GET/PATCH method for + * BIOS configuration pending settings. -- 2.17.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0005-Fix-remove-bios-user-pwd-change-option-via-Redfish.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0005-Fix-remove-bios-user-pwd-change-option-via-Redfish.patch index 75a78abb4..26393bfee 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0005-Fix-remove-bios-user-pwd-change-option-via-Redfish.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/biosconfig/0005-Fix-remove-bios-user-pwd-change-option-via-Redfish.patch @@ -1,7 +1,7 @@ -From fedcdb7887b4d934ee763d75f7988825300c5cef Mon Sep 17 00:00:00 2001 -From: Ayushi Smriti <smriti.ayushi@intel.com> -Date: Thu, 6 May 2021 11:56:38 +0530 -Subject: [PATCH] Fix:remove bios user pwd change option via Redfish +From edc6925e8c0d9f60da1f70c524261efaf05b2710 Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> +Date: Wed, 30 Jun 2021 15:42:06 +0000 +Subject: [PATCH 5/5] Fix:remove bios user pwd change option via Redfish BMC should not provide user bios setup password change option via Redfish as per bios security requirements. Only Admin BIOS setup @@ -15,30 +15,32 @@ https://<ip>/redfish/v1/Systems/system/Bios/Actions/Bios.ChangePassword error occurs for UserPassword parameter and allows for AdminPassword. Signed-off-by: Ayushi Smriti <smriti.ayushi@intel.com> +Change-Id: I169cc6a4f786625d9e8b8dfe56816d52b1740f4c --- - redfish-core/lib/bios.hpp | 9 +++++++++ - 1 file changed, 9 insertions(+) + redfish-core/lib/bios.hpp | 10 ++++++++++ + 1 file changed, 10 insertions(+) diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp -index 12ec472..0416934 100644 +index 0250c59..360a749 100644 --- a/redfish-core/lib/bios.hpp +++ b/redfish-core/lib/bios.hpp -@@ -722,6 +722,15 @@ class BiosChangePassword : public Node - "PasswordName"); - return; - } +@@ -323,6 +323,16 @@ inline void requestRoutesBiosChangePassword(App& app) + asyncResp->res, "ChangePassword", "PasswordName"); + return; + } + -+ // In Intel BIOS, we are not supporting user password in BIOS setup -+ if (userName == "UserPassword") -+ { -+ messages::actionParameterUnknown(asyncResp->res, "ChangePassword", -+ "PasswordName"); -+ return; -+ } ++ // In Intel BIOS, we are not supporting user password in BIOS ++ // setup ++ if (userName == "UserPassword") ++ { ++ messages::actionParameterUnknown( ++ asyncResp->res, "ChangePassword", "PasswordName"); ++ return; ++ } + - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec) { - if (ec) + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec) { + if (ec) -- 2.17.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-EventService-Fix-retry-handling-for-http-client.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-EventService-Fix-retry-handling-for-http-client.patch index bda893a81..7a6818008 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-EventService-Fix-retry-handling-for-http-client.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-EventService-Fix-retry-handling-for-http-client.patch @@ -1,4 +1,4 @@ -From 3d6c3b3e91c04ff8f10bff49bcf2a7d7206c53df Mon Sep 17 00:00:00 2001 +From f74393a9bca899e353be3d0e2dc5c224539fe432 Mon Sep 17 00:00:00 2001 From: Sunitha Harish <sunithaharish04@gmail.com> Date: Fri, 19 Feb 2021 13:38:31 +0530 Subject: [PATCH] EventService : Fix retry handling for http-client @@ -530,10 +530,10 @@ index 992ac2b..feabbba 100644 void setRetryConfig(const uint32_t retryAttempts, diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp -index fa4e41a..c999121 100644 +index 11190ef..a8f7517 100644 --- a/redfish-core/include/event_service_manager.hpp +++ b/redfish-core/include/event_service_manager.hpp -@@ -423,7 +423,7 @@ class Subscription +@@ -422,7 +422,7 @@ class Subscription reqHeaders.emplace_back(std::pair(key, val)); } } @@ -543,5 +543,4 @@ index fa4e41a..c999121 100644 this->eventSeqNum++; } -- -2.17.1 - +2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch index 7cbb406a5..eef0ff065 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch @@ -1,4 +1,4 @@ -From 5f19e5c8ebc5cb0ce331e4ef841526995b6bdb2e Mon Sep 17 00:00:00 2001 +From 4df4a36d6d2cc11c51cc9d53cd441178cc97e39b Mon Sep 17 00:00:00 2001 From: AppaRao Puli <apparao.puli@linux.intel.com> Date: Mon, 22 Feb 2021 17:07:47 +0000 Subject: [PATCH] EventService: https client support @@ -385,10 +385,10 @@ index feabbba..aaf1b2d 100644 { if ((state == ConnState::suspended) || (state == ConnState::terminated)) diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp -index c999121..267c857 100644 +index a8f7517..d4a5bc5 100644 --- a/redfish-core/include/event_service_manager.hpp +++ b/redfish-core/include/event_service_manager.hpp -@@ -398,7 +398,7 @@ class Subscription +@@ -397,7 +397,7 @@ class Subscription { conn = std::make_shared<crow::HttpClient>( crow::connections::systemBus->get_io_context(), id, host, port, @@ -398,5 +398,4 @@ index c999121..267c857 100644 Subscription(const std::shared_ptr<boost::beast::tcp_stream>& adaptor) : -- -2.17.1 - +2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch index cd59ed94d..64948ca0c 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch @@ -1,4 +1,4 @@ -From 0c531d959364192697290c1489d5f7b1bdd7a665 Mon Sep 17 00:00:00 2001 +From 882dc7755083eea32f3d14f7e6c7330d5a9ac66f Mon Sep 17 00:00:00 2001 From: AppaRao Puli <apparao.puli@linux.intel.com> Date: Fri, 12 Mar 2021 18:53:25 +0000 Subject: [PATCH] Add Server-Sent-Events support @@ -30,7 +30,7 @@ Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com> create mode 100644 http/server_sent_event.hpp diff --git a/http/http_connection.hpp b/http/http_connection.hpp -index 6172b3a..fc9fc60 100644 +index fb64014..45b1a68 100644 --- a/http/http_connection.hpp +++ b/http/http_connection.hpp @@ -326,7 +326,7 @@ class Connection : @@ -63,10 +63,10 @@ index 6172b3a..fc9fc60 100644 // delete lambda with self shared_ptr // to enable connection destruction diff --git a/http/http_response.hpp b/http/http_response.hpp -index 7965704..29c56e1 100644 +index 72ff9e9..6bb3aa5 100644 --- a/http/http_response.hpp +++ b/http/http_response.hpp -@@ -13,10 +13,15 @@ namespace crow +@@ -15,10 +15,15 @@ namespace crow template <typename Adaptor, typename Handler> class Connection; @@ -82,7 +82,7 @@ index 7965704..29c56e1 100644 using response_type = boost::beast::http::response<boost::beast::http::string_body>; -@@ -136,8 +141,8 @@ struct Response +@@ -138,8 +143,8 @@ struct Response private: bool completed{}; @@ -93,7 +93,7 @@ index 7965704..29c56e1 100644 // In case of a JSON object, set the Content-Type header void jsonMode() diff --git a/http/routing.hpp b/http/routing.hpp -index dd07523..7ddc6b0 100644 +index af6269e..318fcfe 100644 --- a/http/routing.hpp +++ b/http/routing.hpp @@ -6,6 +6,7 @@ @@ -474,5 +474,4 @@ index 0000000..41d18ed +}; +} // namespace crow -- -2.17.1 - +2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch index 37609c154..78b52eea1 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch @@ -1,4 +1,4 @@ -From bcb80fc9a86555c74b56b5b37615601d3fbfae31 Mon Sep 17 00:00:00 2001 +From a9d994919b677a2650b80fb449cf96baad4f04dd Mon Sep 17 00:00:00 2001 From: AppaRao Puli <apparao.puli@linux.intel.com> Date: Tue, 16 Mar 2021 15:37:24 +0000 Subject: [PATCH] Add SSE style subscription support to eventservice @@ -24,15 +24,15 @@ Change-Id: I7f4b7a34974080739c4ba968ed570489af0474de http/http_connection.hpp | 2 +- include/eventservice_sse.hpp | 75 +++++ .../include/event_service_manager.hpp | 109 +++++-- - redfish-core/include/server_sent_events.hpp | 291 ------------------ - redfish-core/lib/event_service.hpp | 4 +- + redfish-core/include/server_sent_events.hpp | 290 ------------------ + redfish-core/lib/event_service.hpp | 8 +- src/webserver_main.cpp | 2 + - 6 files changed, 163 insertions(+), 320 deletions(-) + 6 files changed, 164 insertions(+), 322 deletions(-) create mode 100644 include/eventservice_sse.hpp delete mode 100644 redfish-core/include/server_sent_events.hpp diff --git a/http/http_connection.hpp b/http/http_connection.hpp -index fc9fc60..3afb4da 100644 +index 45b1a68bf015..ccc2d6a753b7 100644 --- a/http/http_connection.hpp +++ b/http/http_connection.hpp @@ -350,7 +350,7 @@ class Connection : @@ -46,7 +46,7 @@ index fc9fc60..3afb4da 100644 << " is getting upgraded"; diff --git a/include/eventservice_sse.hpp b/include/eventservice_sse.hpp new file mode 100644 -index 0000000..6c98e6e +index 000000000000..14daf00852f5 --- /dev/null +++ b/include/eventservice_sse.hpp @@ -0,0 +1,75 @@ @@ -107,7 +107,7 @@ index 0000000..6c98e6e +inline void requestRoutes(App& app) +{ + BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/SSE") -+ .privileges({"ConfigureComponents", "ConfigureManager"}) ++ .privileges({{"ConfigureComponents", "ConfigureManager"}}) + .serverSentEvent() + .onopen([](std::shared_ptr<crow::SseConnection>& conn, + const crow::Request& req, crow::Response& res) { @@ -126,17 +126,19 @@ index 0000000..6c98e6e +} // namespace eventservice_sse +} // namespace redfish diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp -index fa4e41a..ac644c1 100644 +index ca46aa7dc62f..098134a3a259 100644 --- a/redfish-core/include/event_service_manager.hpp +++ b/redfish-core/include/event_service_manager.hpp -@@ -23,13 +23,15 @@ +@@ -22,15 +22,17 @@ #include <sys/inotify.h> #include <boost/asio/io_context.hpp> +#include <boost/beast/core/span.hpp> #include <boost/container/flat_map.hpp> #include <error_messages.hpp> + #include <event_service_store.hpp> #include <http_client.hpp> + #include <persistent_data.hpp> #include <random.hpp> -#include <server_sent_events.hpp> +#include <server_sent_event.hpp> @@ -146,7 +148,7 @@ index fa4e41a..ac644c1 100644 #include <cstdlib> #include <ctime> #include <fstream> -@@ -46,9 +48,27 @@ using EventServiceConfig = std::tuple<bool, uint32_t, uint32_t>; +@@ -46,9 +48,27 @@ using ReadingsObjType = static constexpr const char* eventFormatType = "Event"; static constexpr const char* metricReportFormatType = "MetricReport"; @@ -199,8 +201,8 @@ index fa4e41a..ac644c1 100644 static const Message* getMsgFromRegistry(const std::string& messageKey, const boost::beast::span<const MessageEntry>& registry) -@@ -401,11 +403,9 @@ class Subscription - path); +@@ -388,11 +390,9 @@ class Subscription : public persistent_data::UserSubscription + path, uriProto); } - Subscription(const std::shared_ptr<boost::beast::tcp_stream>& adaptor) : @@ -214,7 +216,7 @@ index fa4e41a..ac644c1 100644 ~Subscription() = default; -@@ -430,7 +430,7 @@ class Subscription +@@ -417,7 +417,7 @@ class Subscription : public persistent_data::UserSubscription if (sseConn != nullptr) { @@ -223,7 +225,7 @@ index fa4e41a..ac644c1 100644 } } -@@ -520,6 +520,7 @@ class Subscription +@@ -508,6 +508,7 @@ class Subscription : public persistent_data::UserSubscription this->sendEvent( msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace)); @@ -231,7 +233,7 @@ index fa4e41a..ac644c1 100644 } #endif -@@ -590,14 +591,39 @@ class Subscription +@@ -578,14 +579,39 @@ class Subscription : public persistent_data::UserSubscription return eventSeqNum; } @@ -271,8 +273,8 @@ index fa4e41a..ac644c1 100644 + std::string subId; }; - static constexpr const bool defaultEnabledState = true; -@@ -988,6 +1014,8 @@ class EventServiceManager + class EventServiceManager +@@ -942,6 +968,8 @@ class EventServiceManager subValue->updateRetryConfig(retryAttempts, retryTimeoutInterval); subValue->updateRetryPolicy(); @@ -281,7 +283,7 @@ index fa4e41a..ac644c1 100644 return id; } -@@ -1012,11 +1040,40 @@ class EventServiceManager +@@ -970,11 +998,40 @@ class EventServiceManager } } @@ -324,10 +326,10 @@ index fa4e41a..ac644c1 100644 std::vector<std::string> idList; diff --git a/redfish-core/include/server_sent_events.hpp b/redfish-core/include/server_sent_events.hpp deleted file mode 100644 -index 578fa19..0000000 +index 7613d7ba6427..000000000000 --- a/redfish-core/include/server_sent_events.hpp +++ /dev/null -@@ -1,291 +0,0 @@ +@@ -1,290 +0,0 @@ - -/* -// Copyright (c) 2020 Intel Corporation @@ -345,7 +347,6 @@ index 578fa19..0000000 -// limitations under the License. -*/ -#pragma once --#include "node.hpp" - -#include <boost/asio/strand.hpp> -#include <boost/beast/core/span.hpp> @@ -620,32 +621,43 @@ index 578fa19..0000000 - -} // namespace crow diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp -index 64a2009..7c9bb7a 100644 +index f1d6f5007d79..4a2d58a2f1dd 100644 --- a/redfish-core/lib/event_service.hpp +++ b/redfish-core/lib/event_service.hpp -@@ -34,8 +34,6 @@ static constexpr const std::array<const char*, 1> supportedResourceTypes = { +@@ -37,8 +37,6 @@ static constexpr const std::array<const char*, 1> supportedResourceTypes = { "Task"}; #endif -static constexpr const uint8_t maxNoOfSubscriptions = 20; - - class EventService : public Node + inline void requestRoutesEventService(App& app) { - public: -@@ -59,6 +57,8 @@ class EventService : public Node - {"@odata.type", "#EventService.v1_5_0.EventService"}, - {"Id", "EventService"}, - {"Name", "Event Service"}, -+ {"ServerSentEventUri", -+ "/redfish/v1/EventService/Subscriptions/SSE"}, - {"Subscriptions", - {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}}, - {"Actions", + BMCWEB_ROUTE(app, "/redfish/v1/EventService/") +@@ -50,6 +48,8 @@ inline void requestRoutesEventService(App& app) + {"@odata.type", "#EventService.v1_5_0.EventService"}, + {"Id", "EventService"}, + {"Name", "Event Service"}, ++ {"ServerSentEventUri", ++ "/redfish/v1/EventService/Subscriptions/SSE"}, + {"Subscriptions", + {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}}, + {"Actions", +@@ -90,9 +90,7 @@ inline void requestRoutesEventService(App& app) + .privileges(redfish::privileges::patchEventService) + .methods(boost::beast::http::verb::patch)( + [](const crow::Request& req, +- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) +- +- { ++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + std::optional<bool> serviceEnabled; + std::optional<uint32_t> retryAttemps; + std::optional<uint32_t> retryInterval; diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp -index 902c32b..d4bd48c 100644 +index c01accd2e93e..363005105d18 100644 --- a/src/webserver_main.cpp +++ b/src/webserver_main.cpp -@@ -5,6 +5,7 @@ +@@ -6,6 +6,7 @@ #include <cors_preflight.hpp> #include <dbus_monitor.hpp> #include <dbus_singleton.hpp> @@ -653,7 +665,7 @@ index 902c32b..d4bd48c 100644 #include <hostname_monitor.hpp> #include <ibm/management_console_rest.hpp> #include <image_upload.hpp> -@@ -81,6 +82,7 @@ int main(int /*argc*/, char** /*argv*/) +@@ -82,6 +83,7 @@ int main(int /*argc*/, char** /*argv*/) #endif #ifdef BMCWEB_ENABLE_REDFISH diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch index c3e3acbca..79b6e42d7 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch @@ -1,4 +1,4 @@ -From 3dc6f6d807060cf3b38486e4190fd1ba9c66c66b Mon Sep 17 00:00:00 2001 +From e8bf93f1cc374a986896174489719065d0cc49a0 Mon Sep 17 00:00:00 2001 From: AppaRao Puli <apparao.puli@linux.intel.com> Date: Wed, 17 Mar 2021 01:16:50 +0000 Subject: [PATCH] Add EventService SSE filter support @@ -33,18 +33,18 @@ Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com> Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com> Change-Id: I55c6f53bb5e57aa1f2d1601f1a16525a33b13bd2 --- - include/eventservice_sse.hpp | 141 +++++++++++++++++- + include/eventservice_sse.hpp | 145 +++++++++++++++++- redfish-core/include/error_messages.hpp | 9 ++ .../include/event_service_manager.hpp | 5 + redfish-core/lib/event_service.hpp | 5 - redfish-core/src/error_messages.cpp | 26 ++++ - 5 files changed, 177 insertions(+), 9 deletions(-) + 5 files changed, 181 insertions(+), 9 deletions(-) diff --git a/include/eventservice_sse.hpp b/include/eventservice_sse.hpp -index 6c98e6e..01e4126 100644 +index 14daf00..2f22f98 100644 --- a/include/eventservice_sse.hpp +++ b/include/eventservice_sse.hpp -@@ -23,16 +23,149 @@ static bool createSubscription(std::shared_ptr<crow::SseConnection>& conn, +@@ -23,16 +23,153 @@ static bool createSubscription(std::shared_ptr<crow::SseConnection>& conn, } BMCWEB_LOG_DEBUG << "Request query param size: " << req.urlParams.size(); @@ -143,6 +143,10 @@ index 6c98e6e..01e4126 100644 + registryPrefix.assign(supportedRegPrefixes.begin(), + supportedRegPrefixes.end()); + } ++ else ++ { ++ registryPrefix = regPrefixes; ++ } + + for (const std::string& id : msgIds) + { @@ -172,7 +176,7 @@ index 6c98e6e..01e4126 100644 + + if (!validId) + { -+ messages::propertyValueNotInList(res, id, "MessageId"); ++ messages::propertyValueNotInList(res, id, "MessageIds"); + res.end(); + return false; + } @@ -199,10 +203,10 @@ index 6c98e6e..01e4126 100644 std::string id = redfish::EventServiceManager::getInstance().addSubscription(subValue, diff --git a/redfish-core/include/error_messages.hpp b/redfish-core/include/error_messages.hpp -index 7dfdc80..922dae9 100644 +index 10567d1..f29e326 100644 --- a/redfish-core/include/error_messages.hpp +++ b/redfish-core/include/error_messages.hpp -@@ -959,6 +959,15 @@ nlohmann::json mutualExclusiveProperties(const std::string& arg1, +@@ -971,6 +971,15 @@ nlohmann::json mutualExclusiveProperties(const std::string& arg1, void mutualExclusiveProperties(crow::Response& res, const std::string& arg1, const std::string& arg2); @@ -219,7 +223,7 @@ index 7dfdc80..922dae9 100644 } // namespace redfish diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp -index e826207..f201134 100644 +index 098134a..c8fcb33 100644 --- a/redfish-core/include/event_service_manager.hpp +++ b/redfish-core/include/event_service_manager.hpp @@ -55,6 +55,11 @@ static constexpr const char* eventServiceFile = @@ -235,10 +239,10 @@ index e826207..f201134 100644 static std::optional<boost::asio::posix::stream_descriptor> inotifyConn; static constexpr const char* redfishEventLogDir = "/var/log"; diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp -index 7c9bb7a..297a4ea 100644 +index 4a2d58a..67abb95 100644 --- a/redfish-core/lib/event_service.hpp +++ b/redfish-core/lib/event_service.hpp -@@ -18,11 +18,6 @@ +@@ -21,11 +21,6 @@ namespace redfish { @@ -251,10 +255,10 @@ index 7c9bb7a..297a4ea 100644 "TerminateAfterRetries", "SuspendRetries", "RetryForever"}; diff --git a/redfish-core/src/error_messages.cpp b/redfish-core/src/error_messages.cpp -index ad5f819..409adb1 100644 +index 48edaf1..bebb6d8 100644 --- a/redfish-core/src/error_messages.cpp +++ b/redfish-core/src/error_messages.cpp -@@ -2147,6 +2147,32 @@ void mutualExclusiveProperties(crow::Response& res, const std::string& arg1, +@@ -2174,6 +2174,32 @@ void mutualExclusiveProperties(crow::Response& res, const std::string& arg1, addMessageToErrorJson(res.jsonValue, mutualExclusiveProperties(arg1, arg2)); } diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0007-EventService-Log-events-for-subscription-actions.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0007-EventService-Log-events-for-subscription-actions.patch index 0b12671e5..7749ddb72 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0007-EventService-Log-events-for-subscription-actions.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0007-EventService-Log-events-for-subscription-actions.patch @@ -1,6 +1,6 @@ -From 0a1390428fd6f5651669f4306f6105d33a24453c Mon Sep 17 00:00:00 2001 -From: Ayushi Smriti <smriti.ayushi@intel.com> -Date: Mon, 10 May 2021 13:03:37 +0530 +From dad35d6e6736f1c4ab6d739c62b22923ad749ad7 Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> +Date: Tue, 13 Jul 2021 12:30:08 +0000 Subject: [PATCH] EventService: Log events for subscription actions Log redfish event for below 3 actions @@ -27,10 +27,10 @@ Signed-off-by: Ayushi Smriti <smriti.ayushi@intel.com> 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp -index 9952ef1..2b957ea 100644 +index a5b37e5..75f5615 100644 --- a/redfish-core/include/event_service_manager.hpp +++ b/redfish-core/include/event_service_manager.hpp -@@ -22,6 +22,7 @@ +@@ -20,6 +20,7 @@ #include "registries/task_event_message_registry.hpp" #include <sys/inotify.h> @@ -38,7 +38,7 @@ index 9952ef1..2b957ea 100644 #include <boost/asio/io_context.hpp> #include <boost/beast/core/span.hpp> -@@ -800,7 +801,7 @@ class EventServiceManager +@@ -813,7 +814,7 @@ class EventServiceManager return; } @@ -47,7 +47,7 @@ index 9952ef1..2b957ea 100644 { // Persist the config and subscription data. nlohmann::json jsonData; -@@ -897,7 +898,7 @@ class EventServiceManager +@@ -910,7 +911,7 @@ class EventServiceManager if (updateConfig) { @@ -56,7 +56,7 @@ index 9952ef1..2b957ea 100644 } if (updateRetryCfg) -@@ -992,7 +993,7 @@ class EventServiceManager +@@ -1005,7 +1006,7 @@ class EventServiceManager if (updateFile) { @@ -65,7 +65,7 @@ index 9952ef1..2b957ea 100644 } #ifndef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES -@@ -1007,6 +1008,13 @@ class EventServiceManager +@@ -1020,6 +1021,13 @@ class EventServiceManager // Set Subscription ID for back trace subValue->setSubscriptionId(id); @@ -79,7 +79,7 @@ index 9952ef1..2b957ea 100644 return id; } -@@ -1027,7 +1035,14 @@ class EventServiceManager +@@ -1040,7 +1048,14 @@ class EventServiceManager { subscriptionsMap.erase(obj); updateNoOfSubscribersCount(); @@ -95,7 +95,7 @@ index 9952ef1..2b957ea 100644 } } -@@ -1049,6 +1064,18 @@ class EventServiceManager +@@ -1062,6 +1077,18 @@ class EventServiceManager } } @@ -115,18 +115,18 @@ index 9952ef1..2b957ea 100644 { return subscriptionsMap.size(); diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp -index 297a4ea..ed4955e 100644 +index 53a60d3..435c93d 100644 --- a/redfish-core/lib/event_service.hpp +++ b/redfish-core/lib/event_service.hpp -@@ -616,7 +616,7 @@ class EventDestination : public Node - subValue->updateRetryPolicy(); - } - -- EventServiceManager::getInstance().updateSubscriptionData(); -+ EventServiceManager::getInstance().updateSubscription(params[0]); - } +@@ -579,7 +579,7 @@ inline void requestRoutesEventDestination(App& app) + subValue->updateRetryPolicy(); + } - void doDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, +- EventServiceManager::getInstance().updateSubscriptionData(); ++ EventServiceManager::getInstance().updateSubscription(param); + }); + BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") + .privileges({{"ConfigureManager"}}) -- -2.17.1 +2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0008-Add-checks-on-Event-Subscription-input-parameters.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0008-Add-checks-on-Event-Subscription-input-parameters.patch index 874c82e2f..84ceb4ba8 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0008-Add-checks-on-Event-Subscription-input-parameters.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0008-Add-checks-on-Event-Subscription-input-parameters.patch @@ -1,4 +1,4 @@ -From b43da33c7bc9ad4d5eea35c9ba68efdd6ed6d34d Mon Sep 17 00:00:00 2001 +From 05fdea2bb8e486b058d137a067ce1f5c885d2a96 Mon Sep 17 00:00:00 2001 From: Nitin Wankhade <nitinx.arunrao.wankhade@intel.com> Date: Mon, 28 Jun 2021 19:59:57 +0000 Subject: [PATCH] Add checks on Event Subscription input parameters @@ -17,16 +17,16 @@ Tested Change-Id: Iec2cd766c0e137b72706fc2da468d4fefd8fbaae Signed-off-by: Nitin Wankhade <nitinx.arunrao.wankhade@intel.com> --- - redfish-core/lib/event_service.hpp | 30 +++++++++++++++++++++++++++++- - 1 file changed, 29 insertions(+), 1 deletion(-) + redfish-core/lib/event_service.hpp | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp -index ed4955e..0cb0f00 100644 +index 52b01e5..f8a1671 100644 --- a/redfish-core/lib/event_service.hpp +++ b/redfish-core/lib/event_service.hpp -@@ -16,6 +16,10 @@ - #pragma once - #include "event_service_manager.hpp" +@@ -19,6 +19,10 @@ + #include <app.hpp> + #include <registries/privilege_registry.hpp> +#define MAX_CONTEXT_SIZE 256 +#define MAX_DESTINATION_SIZE 1024 @@ -35,50 +35,50 @@ index ed4955e..0cb0f00 100644 namespace redfish { static constexpr const std::array<const char*, 3> supportedRetryPolicies = { -@@ -243,7 +247,11 @@ class EventDestinationCollection : public Node - { - return; - } -- -+ if (destUrl.size() > MAX_DESTINATION_SIZE) -+ { -+ messages::propertySizeExceeded(asyncResp->res, "Destination"); -+ return; -+ } - if (regPrefixes && msgIds) - { - if (regPrefixes->size() && msgIds->size()) -@@ -350,11 +358,31 @@ class EventDestinationCollection : public Node +@@ -220,6 +224,12 @@ inline void requestRoutesEventDestinationCollection(App& app) + return; + } - if (context) - { -+ if (context->size() > MAX_CONTEXT_SIZE) -+ { -+ messages::propertySizeExceeded(asyncResp->res, "Context"); -+ return; -+ } - subValue->customText = *context; - } ++ if (destUrl.size() > MAX_DESTINATION_SIZE) ++ { ++ messages::propertySizeExceeded(asyncResp->res, "Destination"); ++ return; ++ } ++ + if (regPrefixes && msgIds) + { + if (regPrefixes->size() && msgIds->size()) +@@ -330,11 +340,31 @@ inline void requestRoutesEventDestinationCollection(App& app) - if (headers) - { -+ size_t cumulativeLen = 0; + if (context) + { ++ if (context->size() > MAX_CONTEXT_SIZE) ++ { ++ messages::propertySizeExceeded(asyncResp->res, "Context"); ++ return; ++ } + subValue->customText = *context; + } + + if (headers) + { ++ size_t cumulativeLen = 0; + -+ for (nlohmann::json& itr : *headers) -+ { -+ std::string hdr{itr.dump( -+ -1, ' ', true, nlohmann::json::error_handler_t::replace)}; -+ cumulativeLen += hdr.length(); ++ for (nlohmann::json& itr : *headers) ++ { ++ std::string hdr{itr.dump( ++ -1, ' ', true, nlohmann::json::error_handler_t::replace)}; ++ cumulativeLen += hdr.length(); + -+ if (cumulativeLen > MAX_HEADER_SIZE) -+ { -+ messages::propertySizeExceeded(asyncResp->res, ++ if (cumulativeLen > MAX_HEADER_SIZE) ++ { ++ messages::propertySizeExceeded(asyncResp->res, + "HttpHeaders"); -+ return; -+ } -+ } - subValue->httpHeaders = *headers; - } ++ return; ++ } ++ } + subValue->httpHeaders = *headers; + } -- 2.17.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0009-Restructure-Redifsh-EventLog-Transmit-code-flow.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0009-Restructure-Redifsh-EventLog-Transmit-code-flow.patch new file mode 100644 index 000000000..6e635a828 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0009-Restructure-Redifsh-EventLog-Transmit-code-flow.patch @@ -0,0 +1,225 @@ +From 7f45c83c0b3acb08461461c23e0d7add46d9191c Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> +Date: Wed, 14 Jul 2021 14:13:11 +0000 +Subject: [PATCH] Restructure Redfish EventLog Transmit code flow + +In the current implementation: + 1. When Event service is disabled and enabled back after a while, + all the logs during this time span between disable to enable + are dumped to the Event listener. + 2. When two events occur very close (in terms of microseconds) + and they trigger two different iNotify events, the listener + receives both of these events with the same Event ID. + +This occurs as the last log time stamp read from redfish file +and previous time stamp used to generate Event ID's are not +being updated continuously. + +This commit fixes this issue by tweaking the logic to continuously +update the time stamp values (even during when Event Service is +disabled), and also replaces multiple string operations with file +operations. i.e. Instead of looping through the entire Redfish file +until last time stamp read is reached, this fix makes use of +fseek to get to the last read position. + +Tested: + - Subscribed to an event and successfully received Event Logs. + - No Event Logs were received when Event Service was disabled. + - No Dump of past Events after Event Service was enabled. + - Redfish Validator passed + +Change-Id: I87136bee78076b1b3219930813702b3b9d20c157 +Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com> +--- + .../include/event_service_manager.hpp | 108 ++++++++++++------ + 1 file changed, 76 insertions(+), 32 deletions(-) + +diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp +index 430767a..53ed3f6 100644 +--- a/redfish-core/include/event_service_manager.hpp ++++ b/redfish-core/include/event_service_manager.hpp +@@ -133,15 +133,10 @@ static const Message* formatMessage(const std::string_view& messageID) + + namespace event_log + { +-inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID, +- const bool firstEntry = true) ++inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID) + { + static time_t prevTs = 0; + static int index = 0; +- if (firstEntry) +- { +- prevTs = 0; +- } + + // Get the entry timestamp + std::time_t curTs = 0; +@@ -639,6 +634,7 @@ class EventServiceManager + } + + std::string lastEventTStr; ++ std::streampos redfishLogFilePosition{0}; + size_t noOfEventLogSubscribers{0}; + size_t noOfMetricReportSubscribers{0}; + std::shared_ptr<sdbusplus::bus::match::match> matchTelemetryMonitor; +@@ -1204,7 +1200,22 @@ class EventServiceManager + #ifndef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES + void cacheLastEventTimestamp() + { +- lastEventTStr.clear(); ++ // Control comes here when : ++ // 1. Subscription is added and lastEventTStr is empty ++ // 2. lastEventTStr is empty ++ // 3. When a new Redfish file is created ++ ++ if (!lastEventTStr.empty()) ++ { ++ // Control would be here when Redfish file is created. ++ // Reset File Position as new file is created ++ redfishLogFilePosition = 0; ++ return; ++ } ++ ++ // Open the redfish file and read till the last record to get the ++ // last event's time stamp. ++ + std::ifstream logStream(redfishEventLogFile); + if (!logStream.good()) + { +@@ -1212,27 +1223,44 @@ class EventServiceManager + return; + } + std::string logEntry; ++ std::string prev_logEntry; + while (std::getline(logStream, logEntry)) + { +- size_t space = logEntry.find_first_of(' '); +- if (space == std::string::npos) +- { +- // Shouldn't enter here but lets skip it. +- BMCWEB_LOG_DEBUG << "Invalid log entry found."; +- continue; +- } +- lastEventTStr = logEntry.substr(0, space); ++ prev_logEntry = logEntry; ++ redfishLogFilePosition = logStream.tellg(); ++ } ++ ++ if (prev_logEntry.empty()) ++ { ++ BMCWEB_LOG_ERROR ++ << "Last Event Time Stamp Caching Failed : No Records"; ++ redfishLogFilePosition = 0; ++ return; ++ } ++ ++ size_t space = prev_logEntry.find_first_of(' '); ++ if (space == std::string::npos) ++ { ++ // Shouldn't enter here but lets skip it. ++ BMCWEB_LOG_DEBUG << "Invalid log entry found."; ++ BMCWEB_LOG_ERROR << "Last Event Time Stamp Caching Failed"; ++ return; + } ++ lastEventTStr = prev_logEntry.substr(0, space); + BMCWEB_LOG_DEBUG << "Last Event time stamp set: " << lastEventTStr; ++ BMCWEB_LOG_DEBUG << "Next Log Position : " << redfishLogFilePosition; + } + + void readEventLogsFromFile() + { +- if (!serviceEnabled || !noOfEventLogSubscribers) ++ if (lastEventTStr.empty()) + { +- BMCWEB_LOG_DEBUG << "EventService disabled or no Subscriptions."; +- return; ++ // Shouldn't ideally enter here. ++ // Last event Time stamp would be set by now. ++ // Just incase of any failures before. ++ cacheLastEventTimestamp(); + } ++ + std::ifstream logStream(redfishEventLogFile); + if (!logStream.good()) + { +@@ -1242,27 +1270,21 @@ class EventServiceManager + + std::vector<EventLogObjectsType> eventRecords; + +- bool startLogCollection = false; +- bool firstEntry = true; +- + std::string logEntry; ++ ++ // Get the read pointer to the next log to be read. ++ logStream.seekg(redfishLogFilePosition); ++ + while (std::getline(logStream, logEntry)) + { +- if (!startLogCollection && !lastEventTStr.empty()) +- { +- if (boost::starts_with(logEntry, lastEventTStr)) +- { +- startLogCollection = true; +- } +- continue; +- } ++ // Update Pointer position ++ redfishLogFilePosition = logStream.tellg(); + + std::string idStr; +- if (!event_log::getUniqueEntryID(logEntry, idStr, firstEntry)) ++ if (!event_log::getUniqueEntryID(logEntry, idStr)) + { + continue; + } +- firstEntry = false; + + std::string timestamp; + std::string messageID; +@@ -1274,6 +1296,16 @@ class EventServiceManager + continue; + } + ++ lastEventTStr = timestamp; ++ ++ if (!serviceEnabled || !noOfEventLogSubscribers) ++ { ++ // If Service is not enabled, no need to compute ++ // the remaining items below. ++ // But, Loop must continue to keep track of Timestamp ++ continue; ++ } ++ + std::string registryName; + std::string messageKey; + event_log::getRegistryAndMessageKey(messageID, registryName, +@@ -1283,11 +1315,23 @@ class EventServiceManager + continue; + } + +- lastEventTStr = timestamp; + eventRecords.emplace_back(idStr, timestamp, messageID, registryName, + messageKey, messageArgs); + } + ++ if (!serviceEnabled || !noOfEventLogSubscribers) ++ { ++ BMCWEB_LOG_DEBUG << "EventService disabled or no Subscriptions."; ++ return; ++ } ++ ++ if (eventRecords.empty()) ++ { ++ // No Records to send ++ BMCWEB_LOG_DEBUG << "No log entries available to be transferred."; ++ return; ++ } ++ + for (const auto& it : this->subscriptionsMap) + { + std::shared_ptr<Subscription> entry = it.second; +-- +2.25.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README index ae010dafb..cd2e1c2bc 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README @@ -4,16 +4,25 @@ thee gets merged upstream. Upstream revision information: - EventService : Fix retry handling for http-client - https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/40731/20 + https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/40731/21 - EventService: https client support - https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/31735/39 + https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/31735/40 - Add Server-Sent-Events support - https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/41258/6 + https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/41258/7 - Add SSE style subscription support to eventservice - https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/41319/6 + https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/41319/8 - Add EventService SSE filter support - https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/41349/3 + https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/41349/5 + + - EventService Log events for subscription actions + file://telemetry/0007-EventService-Log-events-for-subscription-actions.patch + + - Add checks on Event-Subscription input parameters + file://telemetry/0008-Add-checks-on-Event-Subscription-input-parameters.patch + + - Restructure Redifsh EventLog Transmit code flow + file://telemetry/0009-Restructure-Redifsh-EventLog-Transmit-code-flow.patch diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch index f03e49223..f53b7013f 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch @@ -1,4 +1,4 @@ -From 6acffea563905c00f4b6d00c738fe7516e03c724 Mon Sep 17 00:00:00 2001 +From e37e30943fcb1ba504658ed07d69f950ccf44585 Mon Sep 17 00:00:00 2001 From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> Date: Tue, 13 Apr 2021 13:00:18 +0000 Subject: [PATCH] Add support for MetricDefinition scheme @@ -12,28 +12,28 @@ Tested: - MetricDefinitions response is filled with existing sensors, it works with and without Telemetry service - Validated a presence of MetricDefinition members and its attributes - - Successfully passed RedfishServiceValidator.py using witherspoon image - on QEMU + - Successfully passed RedfishServiceValidator.py using witherspoon + image on QEMU Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com> Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com> Change-Id: I3086e1302e1ba2e5442d1367939fd5507a0cbc00 --- redfish-core/include/redfish.hpp | 3 + - .../include/utils/get_chassis_names.hpp | 58 ++++ + .../include/utils/get_chassis_names.hpp | 58 +++++ .../include/utils/telemetry_utils.hpp | 2 + - redfish-core/lib/metric_definition.hpp | 264 ++++++++++++++++++ + redfish-core/lib/metric_definition.hpp | 242 ++++++++++++++++++ redfish-core/lib/sensors.hpp | 25 +- redfish-core/lib/telemetry_service.hpp | 2 + - 6 files changed, 342 insertions(+), 12 deletions(-) + 6 files changed, 320 insertions(+), 12 deletions(-) create mode 100644 redfish-core/include/utils/get_chassis_names.hpp create mode 100644 redfish-core/lib/metric_definition.hpp diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp -index 4418c3d..594520d 100644 +index 1c7b695..9983b88 100644 --- a/redfish-core/include/redfish.hpp +++ b/redfish-core/include/redfish.hpp -@@ -25,6 +25,7 @@ +@@ -26,6 +26,7 @@ #include "../lib/managers.hpp" #include "../lib/memory.hpp" #include "../lib/message_registries.hpp" @@ -41,15 +41,15 @@ index 4418c3d..594520d 100644 #include "../lib/metric_report.hpp" #include "../lib/metric_report_definition.hpp" #include "../lib/network_protocol.hpp" -@@ -215,6 +216,8 @@ class RedfishService - nodes.emplace_back(std::make_unique<HypervisorResetActionInfo>(app)); +@@ -199,6 +200,8 @@ class RedfishService + requestRoutesMetricReportDefinition(app); + requestRoutesMetricReportCollection(app); + requestRoutesMetricReport(app); ++ requestRoutesMetricDefinitionCollection(app); ++ requestRoutesMetricDefinition(app); + } + }; - nodes.emplace_back(std::make_unique<TelemetryService>(app)); -+ nodes.emplace_back(std::make_unique<MetricDefinitionCollection>(app)); -+ nodes.emplace_back(std::make_unique<MetricDefinition>(app)); - nodes.emplace_back( - std::make_unique<MetricReportDefinitionCollection>(app)); - nodes.emplace_back(std::make_unique<MetricReportDefinition>(app)); diff --git a/redfish-core/include/utils/get_chassis_names.hpp b/redfish-core/include/utils/get_chassis_names.hpp new file mode 100644 index 0000000..0276b6f @@ -129,14 +129,13 @@ index 5872350..1b4f75d 100644 constexpr const char* metricReportUri = diff --git a/redfish-core/lib/metric_definition.hpp b/redfish-core/lib/metric_definition.hpp new file mode 100644 -index 0000000..072fe20 +index 0000000..2443996 --- /dev/null +++ b/redfish-core/lib/metric_definition.hpp -@@ -0,0 +1,264 @@ +@@ -0,0 +1,242 @@ +#pragma once + +#include "async_resp.hpp" -+#include "node.hpp" +#include "sensors.hpp" +#include "utils/get_chassis_names.hpp" +#include "utils/telemetry_utils.hpp" @@ -196,72 +195,67 @@ index 0000000..072fe20 + +} // namespace telemetry + -+class MetricDefinitionCollection : public Node ++inline void requestRoutesMetricDefinitionCollection(App& app) +{ -+ public: -+ MetricDefinitionCollection(App& app) : -+ Node(app, "/redfish/v1/TelemetryService/MetricDefinitions/") -+ { -+ 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"] = "#MetricDefinitionCollection." -+ "MetricDefinitionCollection"; -+ asyncResp->res.jsonValue["@odata.id"] = -+ "/redfish/v1/TelemetryService/MetricDefinitions"; -+ asyncResp->res.jsonValue["Name"] = "Metric Definition Collection"; -+ asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); -+ asyncResp->res.jsonValue["Members@odata.count"] = 0; -+ -+ utils::getChassisNames( -+ [asyncResp](boost::system::error_code ec, -+ const std::vector<std::string>& chassisNames) { -+ if (ec) -+ { -+ messages::internalError(asyncResp->res); -+ BMCWEB_LOG_ERROR << "getChassisNames error: " << ec.value(); -+ return; -+ } -+ -+ auto handleRetrieveUriToDbusMap = -+ [asyncResp](const boost::beast::http::status status, -+ const boost::container::flat_map< -+ std::string, std::string>& uriToDbus) { -+ if (status != boost::beast::http::status::ok) ++ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricDefinitions/") ++ .privileges({{"Login"}}) ++ .methods(boost::beast::http::verb::get)( ++ [](const crow::Request&, ++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { ++ asyncResp->res.jsonValue["@odata.type"] = ++ "#MetricDefinitionCollection." ++ "MetricDefinitionCollection"; ++ asyncResp->res.jsonValue["@odata.id"] = ++ "/redfish/v1/TelemetryService/MetricDefinitions"; ++ asyncResp->res.jsonValue["Name"] = ++ "Metric Definition Collection"; ++ asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); ++ asyncResp->res.jsonValue["Members@odata.count"] = 0; ++ ++ utils::getChassisNames( ++ [asyncResp](boost::system::error_code ec, ++ const std::vector<std::string>& chassisNames) { ++ if (ec) + { -+ BMCWEB_LOG_ERROR -+ << "Failed to retrieve URI to dbus " -+ "sensors map with err " -+ << static_cast<unsigned>(status); + messages::internalError(asyncResp->res); ++ BMCWEB_LOG_ERROR << "getChassisNames error: " ++ << ec.value(); + return; + } -+ telemetry::addMembers(asyncResp->res, uriToDbus); -+ }; + -+ for (const std::string& chassisName : chassisNames) -+ { -+ for (const auto& [sensorNode, _] : sensors::dbus::paths) -+ { -+ BMCWEB_LOG_DEBUG << "Chassis: " << chassisName -+ << " sensor: " << sensorNode; -+ retrieveUriToDbusMap(chassisName, sensorNode.data(), -+ handleRetrieveUriToDbusMap); -+ } -+ } ++ auto handleRetrieveUriToDbusMap = ++ [asyncResp]( ++ 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); ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ telemetry::addMembers(asyncResp->res, ++ uriToDbus); ++ }; ++ ++ for (const std::string& chassisName : chassisNames) ++ { ++ for (const auto& [sensorNode, _] : ++ sensors::dbus::paths) ++ { ++ BMCWEB_LOG_DEBUG << "Chassis: " << chassisName ++ << " sensor: " << sensorNode; ++ retrieveUriToDbusMap( ++ chassisName, sensorNode.data(), ++ handleRetrieveUriToDbusMap); ++ } ++ } ++ }); + }); -+ } -+}; ++} + +namespace telemetry +{ @@ -306,99 +300,83 @@ index 0000000..072fe20 + +} // namespace telemetry + -+class MetricDefinition : public Node ++inline void requestRoutesMetricDefinition(App& app) +{ -+ public: -+ MetricDefinition(App& app) : -+ Node(app, "/redfish/v1/TelemetryService/MetricDefinitions/<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& readingType = params[0]; -+ -+ if (!telemetry::isSensorIdSupported(readingType)) -+ { -+ messages::resourceNotFound(asyncResp->res, "MetricDefinition", -+ readingType); -+ return; -+ } -+ -+ asyncResp->res.jsonValue["MetricProperties"] = nlohmann::json::array(); -+ asyncResp->res.jsonValue["Id"] = readingType; -+ asyncResp->res.jsonValue["Name"] = readingType; -+ asyncResp->res.jsonValue["@odata.id"] = -+ telemetry::metricDefinitionUri + readingType; -+ asyncResp->res.jsonValue["@odata.type"] = -+ "#MetricDefinition.v1_0_3.MetricDefinition"; -+ asyncResp->res.jsonValue["MetricDataType"] = "Decimal"; -+ asyncResp->res.jsonValue["MetricType"] = "Numeric"; -+ asyncResp->res.jsonValue["IsLinear"] = true; -+ asyncResp->res.jsonValue["Implementation"] = "PhysicalSensor"; -+ asyncResp->res.jsonValue["Units"] = -+ sensors::toReadingUnits(readingType); -+ -+ utils::getChassisNames([asyncResp, -+ readingType](boost::system::error_code ec, -+ const std::vector<std::string>& -+ chassisNames) { -+ if (ec) -+ { -+ messages::internalError(asyncResp->res); -+ BMCWEB_LOG_ERROR << "getChassisNames error: " << ec.value(); -+ return; -+ } -+ -+ auto handleRetrieveUriToDbusMap = -+ [asyncResp, readingType]( -+ 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); -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ telemetry::addMetricProperty(*asyncResp, readingType, -+ uriToDbus); -+ }; -+ -+ for (const std::string& chassisName : chassisNames) -+ { -+ for (const auto& [sensorNode, dbusPaths] : sensors::dbus::paths) ++ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricDefinitions/<str>/") ++ .privileges({{"Login"}}) ++ .methods(boost::beast::http::verb::get)( ++ [](const crow::Request&, ++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, ++ const std::string& readingType) { ++ if (!telemetry::isSensorIdSupported(readingType)) + { -+ retrieveUriToDbusMap(chassisName, sensorNode.data(), -+ handleRetrieveUriToDbusMap); ++ messages::resourceNotFound(asyncResp->res, ++ "MetricDefinition", readingType); ++ return; + } -+ } -+ }); -+ } -+}; ++ ++ asyncResp->res.jsonValue["MetricProperties"] = ++ nlohmann::json::array(); ++ asyncResp->res.jsonValue["Id"] = readingType; ++ asyncResp->res.jsonValue["Name"] = readingType; ++ asyncResp->res.jsonValue["@odata.id"] = ++ telemetry::metricDefinitionUri + readingType; ++ asyncResp->res.jsonValue["@odata.type"] = ++ "#MetricDefinition.v1_0_3.MetricDefinition"; ++ asyncResp->res.jsonValue["MetricDataType"] = "Decimal"; ++ asyncResp->res.jsonValue["MetricType"] = "Numeric"; ++ asyncResp->res.jsonValue["IsLinear"] = true; ++ asyncResp->res.jsonValue["Implementation"] = "PhysicalSensor"; ++ asyncResp->res.jsonValue["Units"] = ++ sensors::toReadingUnits(readingType); ++ ++ utils::getChassisNames( ++ [asyncResp, readingType]( ++ boost::system::error_code ec, ++ const std::vector<std::string>& chassisNames) { ++ if (ec) ++ { ++ messages::internalError(asyncResp->res); ++ BMCWEB_LOG_ERROR << "getChassisNames error: " ++ << ec.value(); ++ return; ++ } ++ ++ auto handleRetrieveUriToDbusMap = ++ [asyncResp, readingType]( ++ 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); ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ telemetry::addMetricProperty( ++ *asyncResp, readingType, uriToDbus); ++ }; ++ ++ for (const std::string& chassisName : chassisNames) ++ { ++ for (const auto& [sensorNode, dbusPaths] : ++ sensors::dbus::paths) ++ { ++ retrieveUriToDbusMap( ++ chassisName, sensorNode.data(), ++ handleRetrieveUriToDbusMap); ++ } ++ } ++ }); ++ }); ++} + +} // namespace redfish diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp -index e7f4cde..b16b014 100644 +index d986565..bccbb94 100644 --- a/redfish-core/lib/sensors.hpp +++ b/redfish-core/lib/sensors.hpp @@ -111,46 +111,47 @@ inline const char* toReadingType(const std::string& sensorType) @@ -474,18 +452,17 @@ index e7f4cde..b16b014 100644 else { diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp -index 9ec0737..de9c800 100644 +index ad86d5c..c4962e9 100644 --- a/redfish-core/lib/telemetry_service.hpp +++ b/redfish-core/lib/telemetry_service.hpp -@@ -32,6 +32,8 @@ class TelemetryService : public Node - asyncResp->res.jsonValue["Id"] = "TelemetryService"; - asyncResp->res.jsonValue["Name"] = "Telemetry Service"; +@@ -29,6 +29,8 @@ inline void requestRoutesTelemetryService(App& app) + "/redfish/v1/TelemetryService/MetricReportDefinitions"; + asyncResp->res.jsonValue["MetricReports"]["@odata.id"] = + "/redfish/v1/TelemetryService/MetricReports"; ++ asyncResp->res.jsonValue["MetricDefinitions"]["@odata.id"] = ++ "/redfish/v1/TelemetryService/MetricDefinitions"; -+ asyncResp->res.jsonValue["MetricDefinitions"]["@odata.id"] = -+ "/redfish/v1/TelemetryService/MetricDefinitions"; - asyncResp->res.jsonValue["MetricReportDefinitions"]["@odata.id"] = - "/redfish/v1/TelemetryService/MetricReportDefinitions"; - asyncResp->res.jsonValue["MetricReports"]["@odata.id"] = + crow::connections::systemBus->async_method_call( + [asyncResp]( -- -2.17.1 - +2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Sync-Telmetry-service-with-EventService.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Sync-Telmetry-service-with-EventService.patch index 9b77c29df..0ca58a114 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Sync-Telmetry-service-with-EventService.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Sync-Telmetry-service-with-EventService.patch @@ -1,4 +1,4 @@ -From 206411b4c9b603e7b0edf63e03c0ef7bf10b09b2 Mon Sep 17 00:00:00 2001 +From 277d261ef3b1723c9d198baf4b84d2e01a7460b8 Mon Sep 17 00:00:00 2001 From: "Wludzik, Jozef" <jozef.wludzik@intel.com> Date: Tue, 15 Dec 2020 12:30:31 +0100 Subject: [PATCH] Sync Telmetry service with EventService @@ -22,7 +22,7 @@ Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com> 2 files changed, 69 insertions(+), 115 deletions(-) diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp -index a1761bb..0e2ebfd 100644 +index 11190ef..ffe9435 100644 --- a/redfish-core/include/event_service_manager.hpp +++ b/redfish-core/include/event_service_manager.hpp @@ -14,6 +14,7 @@ @@ -30,10 +30,10 @@ index a1761bb..0e2ebfd 100644 */ #pragma once +#include "metric_report.hpp" - #include "node.hpp" #include "registries.hpp" #include "registries/base_message_registry.hpp" -@@ -523,47 +524,32 @@ class Subscription + #include "registries/openbmc_message_registry.hpp" +@@ -522,47 +523,32 @@ class Subscription } #endif @@ -92,7 +92,7 @@ index a1761bb..0e2ebfd 100644 this->sendEvent( msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace)); } -@@ -1359,75 +1345,6 @@ class EventServiceManager +@@ -1358,75 +1344,6 @@ class EventServiceManager } #endif @@ -168,7 +168,7 @@ index a1761bb..0e2ebfd 100644 void unregisterMetricReportSignal() { if (matchTelemetryMonitor) -@@ -1447,9 +1364,11 @@ class EventServiceManager +@@ -1446,9 +1363,11 @@ class EventServiceManager } BMCWEB_LOG_DEBUG << "Metrics report signal - Register"; @@ -183,7 +183,7 @@ index a1761bb..0e2ebfd 100644 matchTelemetryMonitor = std::make_shared<sdbusplus::bus::match::match>( *crow::connections::systemBus, matchStr, -@@ -1460,10 +1379,43 @@ class EventServiceManager +@@ -1459,10 +1378,43 @@ class EventServiceManager return; } @@ -232,10 +232,10 @@ index a1761bb..0e2ebfd 100644 } diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp -index ad15a05..18a6dcc 100644 +index 66f4f93..a43f6a6 100644 --- a/redfish-core/lib/metric_report.hpp +++ b/redfish-core/lib/metric_report.hpp -@@ -31,16 +31,14 @@ inline nlohmann::json toMetricValues(const Readings& readings) +@@ -32,16 +32,14 @@ inline nlohmann::json toMetricValues(const Readings& readings) return metricValues; } @@ -258,7 +258,7 @@ index ad15a05..18a6dcc 100644 telemetry::metricReportDefinitionUri + id; const TimestampReadings* timestampReadings = -@@ -48,14 +46,14 @@ inline void fillReport(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, +@@ -49,14 +47,14 @@ inline void fillReport(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, if (!timestampReadings) { BMCWEB_LOG_ERROR << "Property type mismatch or property is missing"; @@ -277,18 +277,18 @@ index ad15a05..18a6dcc 100644 } } // namespace telemetry -@@ -145,7 +143,11 @@ class MetricReport : public Node - return; - } +@@ -117,7 +115,11 @@ inline void requestRoutesMetricReport(App& app) + return; + } -- telemetry::fillReport(asyncResp, id, ret); -+ if (!telemetry::fillReport(asyncResp->res.jsonValue, id, -+ ret)) -+ { -+ messages::internalError(asyncResp->res); -+ } - }, - telemetry::service, reportPath, - "org.freedesktop.DBus.Properties", "Get", +- telemetry::fillReport(asyncResp, id, ret); ++ if (!telemetry::fillReport( ++ asyncResp->res.jsonValue, id, ret)) ++ { ++ messages::internalError(asyncResp->res); ++ } + }, + telemetry::service, reportPath, + "org.freedesktop.DBus.Properties", "Get", -- 2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Revert-Remove-LogService-from-TelemetryService.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Revert-Remove-LogService-from-TelemetryService.patch index 645351a51..987a43b4c 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Revert-Remove-LogService-from-TelemetryService.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Revert-Remove-LogService-from-TelemetryService.patch @@ -1,6 +1,6 @@ -From dc7e43c70285596195efd9d328b303091794278c Mon Sep 17 00:00:00 2001 +From 472ac5f15a19917042852b243e8b668b3ab49e32 Mon Sep 17 00:00:00 2001 From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> -Date: Mon, 31 May 2021 10:08:57 +0000 +Date: Tue, 22 Jun 2021 13:59:48 +0000 Subject: [PATCH] Revert "Remove LogService from TelemetryService" This reverts commit 2b3da45876aac57a36d3093379a992d699e7e396. @@ -9,18 +9,18 @@ This reverts commit 2b3da45876aac57a36d3093379a992d699e7e396. 1 file changed, 2 insertions(+) diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp -index de9c800..f05bf6d 100644 +index 37221c3..f3a1efb 100644 --- a/redfish-core/lib/telemetry_service.hpp +++ b/redfish-core/lib/telemetry_service.hpp -@@ -38,6 +38,8 @@ class TelemetryService : public Node - "/redfish/v1/TelemetryService/MetricReportDefinitions"; - asyncResp->res.jsonValue["MetricReports"]["@odata.id"] = - "/redfish/v1/TelemetryService/MetricReports"; -+ asyncResp->res.jsonValue["LogService"]["@odata.id"] = -+ "/redfish/v1/Managers/bmc/LogServices/Journal"; +@@ -30,6 +30,8 @@ inline void requestRoutesTelemetryService(App& app) + "/redfish/v1/TelemetryService/MetricReports"; + asyncResp->res.jsonValue["MetricDefinitions"]["@odata.id"] = + "/redfish/v1/TelemetryService/MetricDefinitions"; ++ asyncResp->res.jsonValue["LogService"]["@odata.id"] = ++ "/redfish/v1/Managers/bmc/LogServices/Journal"; - crow::connections::systemBus->async_method_call( - [asyncResp]( + crow::connections::systemBus->async_method_call( + [asyncResp]( -- 2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Switched-bmcweb-to-use-new-telemetry-service-API.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Switched-bmcweb-to-use-new-telemetry-service-API.patch new file mode 100644 index 000000000..4e326ff88 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Switched-bmcweb-to-use-new-telemetry-service-API.patch @@ -0,0 +1,301 @@ +From 51869fd549cd826981ad30c6cdea4c4e94a972db Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> +Date: Thu, 17 Jun 2021 13:37:57 +0000 +Subject: [PATCH] Switched bmcweb to use new telemetry service API + +Added support for multiple MetricProperties. Added support for new +parameters: CollectionTimeScope, CollectionDuration. + +Tested: + - It is possible to create MetricReportDefinitions with multiple + MetricProperties. + - Stub values for new parameters are correctly passed to telemetry + service. + - All existing telemetry service functionalities remain unchanged. + +Change-Id: I2cd17069e3ea015c8f5571c29278f1d50536272a +Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com> +--- + redfish-core/lib/metric_report_definition.hpp | 212 ++++++++++-------- + 1 file changed, 114 insertions(+), 98 deletions(-) + +diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp +index a0c4f1d..7c26787 100644 +--- a/redfish-core/lib/metric_report_definition.hpp ++++ b/redfish-core/lib/metric_report_definition.hpp +@@ -7,6 +7,8 @@ + #include <app.hpp> + #include <boost/container/flat_map.hpp> + #include <registries/privilege_registry.hpp> ++#include <sdbusplus/asio/property.hpp> ++#include <sdbusplus/unpack_properties.hpp> + + #include <tuple> + #include <variant> +@@ -17,87 +19,90 @@ namespace redfish + namespace telemetry + { + +-using ReadingParameters = +- std::vector<std::tuple<sdbusplus::message::object_path, std::string, +- std::string, std::string>>; ++using ReadingParameters = std::vector< ++ std::tuple<std::vector<sdbusplus::message::object_path>, std::string, ++ std::string, std::string, std::string, uint64_t>>; + + inline void fillReportDefinition( + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id, + const std::vector< +- std::pair<std::string, std::variant<std::string, bool, uint64_t, +- ReadingParameters>>>& ret) ++ std::pair<std::string, std::variant<std::monostate, std::string, bool, ++ uint64_t, ReadingParameters>>>& ++ properties) + { +- asyncResp->res.jsonValue["@odata.type"] = +- "#MetricReportDefinition.v1_3_0.MetricReportDefinition"; +- asyncResp->res.jsonValue["@odata.id"] = +- telemetry::metricReportDefinitionUri + id; +- asyncResp->res.jsonValue["Id"] = id; +- asyncResp->res.jsonValue["Name"] = id; +- asyncResp->res.jsonValue["MetricReport"]["@odata.id"] = +- telemetry::metricReportUri + id; +- asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; +- asyncResp->res.jsonValue["ReportUpdates"] = "Overwrite"; +- +- const bool* emitsReadingsUpdate = nullptr; +- const bool* logToMetricReportsCollection = nullptr; +- const ReadingParameters* readingParams = nullptr; +- const std::string* reportingType = nullptr; +- const uint64_t* interval = nullptr; +- for (const auto& [key, var] : ret) ++ try + { +- if (key == "EmitsReadingsUpdate") ++ bool emitsReadingsUpdate = false; ++ bool logToMetricReportsCollection = false; ++ ReadingParameters readingParams; ++ std::string reportingType; ++ uint64_t interval = 0u; ++ ++ sdbusplus::unpackProperties( ++ properties, "EmitsReadingsUpdate", emitsReadingsUpdate, ++ "LogToMetricReportsCollection", logToMetricReportsCollection, ++ "ReadingParametersFutureVersion", readingParams, "ReportingType", ++ reportingType, "Interval", interval); ++ ++ std::vector<std::string> redfishReportActions; ++ redfishReportActions.reserve(2); ++ if (emitsReadingsUpdate) + { +- emitsReadingsUpdate = std::get_if<bool>(&var); ++ redfishReportActions.emplace_back("RedfishEvent"); + } +- else if (key == "LogToMetricReportsCollection") ++ if (logToMetricReportsCollection) + { +- logToMetricReportsCollection = std::get_if<bool>(&var); ++ redfishReportActions.emplace_back("LogToMetricReportsCollection"); + } +- else if (key == "ReadingParameters") +- { +- readingParams = std::get_if<ReadingParameters>(&var); +- } +- else if (key == "ReportingType") +- { +- reportingType = std::get_if<std::string>(&var); +- } +- else if (key == "Interval") ++ ++ nlohmann::json metrics = nlohmann::json::array(); ++ for (auto& [sensorPath, operationType, id, metadata, ++ collectionTimeScope, collectionDuration] : readingParams) + { +- interval = std::get_if<uint64_t>(&var); ++ std::vector<std::string> metricProperties; ++ ++ nlohmann::json parsedMetadata = nlohmann::json::parse(metadata); ++ if (!json_util::readJson(parsedMetadata, asyncResp->res, ++ "MetricProperties", metricProperties)) ++ { ++ BMCWEB_LOG_ERROR << "Failed to read metadata"; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ ++ metrics.push_back({ ++ {"MetricId", id}, ++ {"MetricProperties", std::move(metricProperties)}, ++ }); + } +- } +- if (!emitsReadingsUpdate || !logToMetricReportsCollection || +- !readingParams || !reportingType || !interval) +- { +- BMCWEB_LOG_ERROR << "Property type mismatch or property is missing"; +- messages::internalError(asyncResp->res); +- return; +- } + +- std::vector<std::string> redfishReportActions; +- redfishReportActions.reserve(2); +- if (*emitsReadingsUpdate) +- { +- redfishReportActions.emplace_back("RedfishEvent"); ++ asyncResp->res.jsonValue["@odata.type"] = ++ "#MetricReportDefinition.v1_3_0.MetricReportDefinition"; ++ asyncResp->res.jsonValue["@odata.id"] = ++ telemetry::metricReportDefinitionUri + id; ++ asyncResp->res.jsonValue["Id"] = id; ++ asyncResp->res.jsonValue["Name"] = id; ++ asyncResp->res.jsonValue["MetricReport"]["@odata.id"] = ++ telemetry::metricReportUri + id; ++ asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; ++ asyncResp->res.jsonValue["ReportUpdates"] = "Overwrite"; ++ asyncResp->res.jsonValue["Metrics"] = metrics; ++ asyncResp->res.jsonValue["MetricReportDefinitionType"] = reportingType; ++ asyncResp->res.jsonValue["ReportActions"] = redfishReportActions; ++ asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] = ++ time_utils::toDurationString(std::chrono::milliseconds(interval)); + } +- if (*logToMetricReportsCollection) ++ catch (const sdbusplus::exception::UnpackPropertyError& error) + { +- redfishReportActions.emplace_back("LogToMetricReportsCollection"); ++ BMCWEB_LOG_ERROR << error.what() << ", property: " ++ << error.propertyName + ", reason: " << error.reason; ++ messages::internalError(asyncResp->res); + } +- +- nlohmann::json metrics = nlohmann::json::array(); +- for (auto& [sensorPath, operationType, id, metadata] : *readingParams) ++ catch (const nlohmann::json::parse_error& e) + { +- metrics.push_back({ +- {"MetricId", id}, +- {"MetricProperties", {metadata}}, +- }); ++ BMCWEB_LOG_ERROR << "Failed to parse metadata: " << e.what(); ++ messages::internalError(asyncResp->res); + } +- asyncResp->res.jsonValue["Metrics"] = metrics; +- asyncResp->res.jsonValue["MetricReportDefinitionType"] = *reportingType; +- asyncResp->res.jsonValue["ReportActions"] = redfishReportActions; +- asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] = +- time_utils::toDurationString(std::chrono::milliseconds(*interval)); + } + + struct AddReportArgs +@@ -275,6 +280,11 @@ class AddReport + + for (const auto& [id, uris] : args.metrics) + { ++ std::vector<sdbusplus::message::object_path> dbusPaths; ++ dbusPaths.reserve(uris.size()); ++ nlohmann::json metadata; ++ metadata["MetricProperties"] = nlohmann::json::array(); ++ + for (size_t i = 0; i < uris.size(); i++) + { + const std::string& uri = uris[i]; +@@ -291,8 +301,12 @@ class AddReport + } + + const std::string& dbusPath = el->second; +- readingParams.emplace_back(dbusPath, "SINGLE", id, uri); ++ dbusPaths.emplace_back(dbusPath); ++ metadata["MetricProperties"].emplace_back(uri); + } ++ ++ readingParams.emplace_back(dbusPaths, "SINGLE", id, metadata.dump(), ++ "Point", 0u); + } + const std::shared_ptr<bmcweb::AsyncResp> aResp = asyncResp; + crow::connections::systemBus->async_method_call( +@@ -330,10 +344,10 @@ class AddReport + messages::created(aResp->res); + }, + telemetry::service, "/xyz/openbmc_project/Telemetry/Reports", +- "xyz.openbmc_project.Telemetry.ReportManager", "AddReport", +- "TelemetryService/" + args.name, args.reportingType, +- args.emitsReadingsUpdate, args.logToMetricReportsCollection, +- args.interval, readingParams); ++ "xyz.openbmc_project.Telemetry.ReportManager", ++ "AddReportFutureVersion", "TelemetryService/" + args.name, ++ args.reportingType, args.emitsReadingsUpdate, ++ args.logToMetricReportsCollection, args.interval, readingParams); + } + + void insert(const boost::container::flat_map<std::string, std::string>& el) +@@ -415,37 +429,39 @@ inline void requestRoutesMetricReportDefinition(App& app) + BMCWEB_ROUTE(app, + "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") + .privileges(redfish::privileges::getMetricReportDefinition) +- .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; +- } ++ .methods( ++ boost::beast::http::verb::get)([](const crow::Request&, ++ const std::shared_ptr< ++ bmcweb::AsyncResp>& asyncResp, ++ const std::string& id) { ++ sdbusplus::asio::getAllProperties( ++ *crow::connections::systemBus, telemetry::service, ++ telemetry::getDbusReportPath(id), telemetry::reportInterface, ++ [asyncResp, ++ id](boost::system::error_code ec, ++ const std::vector<std::pair< ++ std::string, ++ std::variant<std::monostate, std::string, bool, ++ uint64_t, telemetry::ReadingParameters>>>& ++ properties) { ++ 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; ++ } ++ ++ telemetry::fillReportDefinition(asyncResp, id, properties); ++ }); ++ }); + +- 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(redfish::privileges::deleteMetricReportDefinitionCollection) +-- +2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Add-support-for-MetricDefinition-property-in-MetricReport.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Add-support-for-MetricDefinition-property-in-MetricReport.patch new file mode 100644 index 000000000..d3a7c0a35 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Add-support-for-MetricDefinition-property-in-MetricReport.patch @@ -0,0 +1,268 @@ +From d37ba16f837380ea5fbd7fae2d0f2e229c601754 Mon Sep 17 00:00:00 2001 +From: Szymon Dompke <szymon.dompke@intel.com> +Date: Mon, 28 Jun 2021 11:10:23 +0200 +Subject: [PATCH] Add support for MetricDefinition property in MetricReport + +Added MetricDefinition as part of MetricValues array returned by +MetricReport. It contains single @odata.id with URI to proper +MetricDefinition resource - depending on MetricProperty. + +Testing done: +- GET request on redfish/v1/TelemetryService/MetricReports + got response with MetricDefinition and proper id inside + MetricValues array. + +Testing steps: +1. POST on redfish/v1/TelemetryService/MetricReportDefinitions + with body: +{ + "Id": "PeriodicReport_1", + "MetricReportDefinitionType": "Periodic", + "ReportActions": [ + "LogToMetricReportsCollection", + "RedfishEvent" + ], + "Metrics": [ + { + "MetricId": "sensor_1", + "MetricProperties": [ + "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/1/Reading" + ] + } + ], + "Schedule": { + "RecurrenceInterval": "PT10S" + } +} + +2. GET on redfish/v1/TelemetryService/MetricReports/PeriodicReport_1 + should return: +{ + "@odata.id": + "/redfish/v1/TelemetryService/MetricReports/PeriodicReport_1", + "@odata.type": "#MetricReport.v1_3_0.MetricReport", + "Id": "PeriodicReport_1", + "MetricReportDefinition": { + "@odata.id": + "/redfish/v1/TelemetryService/MetricReportDefinitions/PeriodicReport_1" + }, + "MetricValues": [ + { + "MetricDefinition": { + "@odata.id": + "/redfish/v1/TelemetryService/MetricDefinitions/Rotational" + }, + "MetricId": "sensor_1", + "MetricProperty": + "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/1/Reading", + "MetricValue": "nan", + "Timestamp": "1970-01-01T00:03:21+00:00" + } + ], + "Name": "PeriodicReport_1", + "Timestamp": "1970-01-01T00:03:21+00:00" +} + +Change-Id: I7181c612f9b443015d551259bae25303aa436822 +Signed-off-by: Szymon Dompke <szymon.dompke@intel.com> +--- + meson.build | 4 +- + .../include/utils/telemetry_utils.hpp | 40 ++++++++++++ + redfish-core/lib/metric_report.hpp | 64 +++++++++++++++---- + redfish-core/lib/sensors.hpp | 2 + + 4 files changed, 95 insertions(+), 15 deletions(-) + +diff --git a/meson.build b/meson.build +index bdc514b..aadfd7d 100644 +--- a/meson.build ++++ b/meson.build +@@ -354,6 +354,8 @@ srcfiles_unittest = ['include/ut/dbus_utility_test.cpp', + 'redfish-core/ut/time_utils_test.cpp', + 'http/ut/utility_test.cpp'] + ++srcfiles_unittest_dependencies = ['redfish-core/src/error_messages.cpp'] ++ + # Gather the Configuration data + + conf_data = configuration_data() +@@ -411,7 +413,7 @@ executable('bmcweb',srcfiles_bmcweb, + if(get_option('tests').enabled()) + foreach src_test : srcfiles_unittest + testname = src_test.split('/')[-1].split('.')[0] +- test(testname,executable(testname,src_test, ++ test(testname,executable(testname,[src_test] + srcfiles_unittest_dependencies, + include_directories : incdir, + install_dir: bindir, + dependencies: [ +diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp +index 1b4f75d..c0c5ba3 100644 +--- a/redfish-core/include/utils/telemetry_utils.hpp ++++ b/redfish-core/include/utils/telemetry_utils.hpp +@@ -17,6 +17,46 @@ constexpr const char* metricReportDefinitionUri = + constexpr const char* metricReportUri = + "/redfish/v1/TelemetryService/MetricReports/"; + ++inline std::optional<nlohmann::json> ++ getMetadataJson(const std::string& metadataStr) ++{ ++ std::optional<nlohmann::json> res = ++ nlohmann::json::parse(metadataStr, nullptr, false); ++ if (res->is_discarded()) ++ { ++ BMCWEB_LOG_ERROR << "Malformed reading metatadata JSON provided by " ++ "telemetry service."; ++ return std::nullopt; ++ } ++ return res; ++} ++ ++inline std::optional<std::string> ++ readStringFromMetadata(const nlohmann::json& metadataJson, const char* key) ++{ ++ std::optional<std::string> res; ++ if (auto it = metadataJson.find(key); it != metadataJson.end()) ++ { ++ if (const std::string* value = it->get_ptr<const std::string*>()) ++ { ++ res = *value; ++ } ++ else ++ { ++ BMCWEB_LOG_ERROR << "Incorrect reading metatadata JSON provided by " ++ "telemetry service. Missing key '" ++ << key << "'."; ++ } ++ } ++ else ++ { ++ BMCWEB_LOG_ERROR << "Incorrect reading metatadata JSON provided by " ++ "telemetry service. Key '" ++ << key << "' has a wrong type."; ++ } ++ return res; ++} ++ + inline void + getReportCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& uri) +diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp +index 7fe281d..13bf792 100644 +--- a/redfish-core/lib/metric_report.hpp ++++ b/redfish-core/lib/metric_report.hpp +@@ -1,5 +1,6 @@ + #pragma once + ++#include "sensors.hpp" + #include "utils/telemetry_utils.hpp" + + #include <app.hpp> +@@ -15,34 +16,56 @@ using Readings = + std::vector<std::tuple<std::string, std::string, double, uint64_t>>; + using TimestampReadings = std::tuple<uint64_t, Readings>; + +-inline nlohmann::json toMetricValues(const Readings& readings) ++inline bool fillMetricValues(nlohmann::json& metricValues, ++ const Readings& readings) + { +- nlohmann::json metricValues = nlohmann::json::array_t(); +- +- for (auto& [id, metadata, sensorValue, timestamp] : readings) ++ for (auto& [id, metadataStr, sensorValue, timestamp] : readings) + { ++ std::optional<nlohmann::json> readingMetadataJson = ++ getMetadataJson(metadataStr); ++ if (!readingMetadataJson) ++ { ++ return false; ++ } ++ ++ std::optional<std::string> sensorDbusPath = ++ readStringFromMetadata(*readingMetadataJson, "SensorDbusPath"); ++ if (!sensorDbusPath) ++ { ++ return false; ++ } ++ ++ std::optional<std::string> sensorRedfishUri = ++ readStringFromMetadata(*readingMetadataJson, "SensorRedfishUri"); ++ if (!sensorRedfishUri) ++ { ++ return false; ++ } ++ ++ std::string metricDefinition = ++ std::string(metricDefinitionUri) + ++ sensors::toReadingType( ++ sdbusplus::message::object_path(*sensorDbusPath) ++ .parent_path() ++ .filename()); ++ + metricValues.push_back({ ++ {"MetricDefinition", ++ nlohmann::json{{"@odata.id", metricDefinition}}}, + {"MetricId", id}, +- {"MetricProperty", metadata}, ++ {"MetricProperty", *sensorRedfishUri}, + {"MetricValue", std::to_string(sensorValue)}, + {"Timestamp", + crow::utility::getDateTime(static_cast<time_t>(timestamp))}, + }); + } + +- return metricValues; ++ return true; + } + + inline bool fillReport(nlohmann::json& json, const std::string& id, + const std::variant<TimestampReadings>& var) + { +- json["@odata.type"] = "#MetricReport.v1_3_0.MetricReport"; +- json["@odata.id"] = telemetry::metricReportUri + id; +- json["Id"] = id; +- json["Name"] = id; +- json["MetricReportDefinition"]["@odata.id"] = +- telemetry::metricReportDefinitionUri + id; +- + const TimestampReadings* timestampReadings = + std::get_if<TimestampReadings>(&var); + if (!timestampReadings) +@@ -52,9 +75,22 @@ inline bool fillReport(nlohmann::json& json, const std::string& id, + } + + const auto& [timestamp, readings] = *timestampReadings; ++ nlohmann::json metricValues = nlohmann::json::array(); ++ if (!fillMetricValues(metricValues, readings)) ++ { ++ return false; ++ } ++ ++ json["@odata.type"] = "#MetricReport.v1_3_0.MetricReport"; ++ json["@odata.id"] = telemetry::metricReportUri + id; ++ json["Id"] = id; ++ json["Name"] = id; ++ json["MetricReportDefinition"]["@odata.id"] = ++ telemetry::metricReportDefinitionUri + id; + json["Timestamp"] = + crow::utility::getDateTime(static_cast<time_t>(timestamp)); +- json["MetricValues"] = toMetricValues(readings); ++ json["MetricValues"] = metricValues; ++ + return true; + } + } // namespace telemetry +diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp +index bccbb94..3e1d003 100644 +--- a/redfish-core/lib/sensors.hpp ++++ b/redfish-core/lib/sensors.hpp +@@ -21,6 +21,8 @@ + #include <boost/container/flat_map.hpp> + #include <boost/range/algorithm/replace_copy_if.hpp> + #include <dbus_singleton.hpp> ++#include <dbus_utility.hpp> ++#include <error_messages.hpp> + #include <registries/privilege_registry.hpp> + #include <utils/json_utils.hpp> + +-- +2.25.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-Generalize-ReadingType-in-MetricDefinition.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-Generalize-ReadingType-in-MetricDefinition.patch new file mode 100644 index 000000000..1cdd59d4b --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-Generalize-ReadingType-in-MetricDefinition.patch @@ -0,0 +1,168 @@ +From 872a7bdb9c272944914d7c5babc751e6bb33afec Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Adrian=20Ambro=C5=BCewicz?= <adrian.ambrozewicz@intel.com> +Date: Tue, 3 Aug 2021 13:59:31 +0200 +Subject: [PATCH] Generalize ReadingType in MetricDefinition + +Recent addition of PMT required adding new type of sensor 'count', which +doesnt comply with any of Redfish-defined Sensor.ReadingType values. + +To support property of this kind MetricDefinition implementation was +altered to support sensor types not covered by Redfish types by +a 'fallback' to direct usage of sensor type. Populating 'Units' was also +modified, so it won't be shown if value does not have any units mapped. + +Testing: +- PMT counters are shown properly in MetricDefinitions/Count +- Redfish Validator passes +--- + redfish-core/lib/metric_definition.hpp | 63 ++++++++++++++++---------- + 1 file changed, 39 insertions(+), 24 deletions(-) + +diff --git a/redfish-core/lib/metric_definition.hpp b/redfish-core/lib/metric_definition.hpp +index 2443996..fcab44d 100644 +--- a/redfish-core/lib/metric_definition.hpp ++++ b/redfish-core/lib/metric_definition.hpp +@@ -11,6 +11,18 @@ namespace redfish + namespace telemetry + { + ++std::string groupName(const std::string& sensorType) ++{ ++ std::string group = sensors::toReadingType(sensorType); ++ if (group.empty()) ++ { ++ // Fallback for types not covered by standard Redfish Sensor.ReadingType ++ group = sensorType; ++ group[0] = static_cast<char>(std::toupper(group[0])); ++ } ++ return group; ++} ++ + void addMembers(crow::Response& res, + const boost::container::flat_map<std::string, std::string>& el) + { +@@ -30,8 +42,7 @@ void addMembers(crow::Response& res, + nlohmann::json& members = res.jsonValue["Members"]; + + const std::string odataId = +- std::string(telemetry::metricDefinitionUri) + +- sensors::toReadingType(type); ++ std::string(telemetry::metricDefinitionUri) + groupName(type); + + const auto it = std::find_if(members.begin(), members.end(), + [&odataId](const nlohmann::json& item) { +@@ -125,15 +136,15 @@ inline void requestRoutesMetricDefinitionCollection(App& app) + namespace telemetry + { + +-bool isSensorIdSupported(std::string_view readingType) ++bool isSensorIdSupported(std::string_view group) + { + for (const std::pair<std::string_view, std::vector<const char*>>& + typeToPaths : sensors::dbus::paths) + { + for (const char* supportedPath : typeToPaths.second) + { +- if (readingType == +- sensors::toReadingType( ++ if (group == ++ groupName( + sdbusplus::message::object_path(supportedPath).filename())) + { + return true; +@@ -144,7 +155,7 @@ bool isSensorIdSupported(std::string_view readingType) + } + + void addMetricProperty( +- bmcweb::AsyncResp& asyncResp, const std::string& readingType, ++ bmcweb::AsyncResp& asyncResp, const std::string& group, + const boost::container::flat_map<std::string, std::string>& el) + { + nlohmann::json& metricProperties = +@@ -155,7 +166,7 @@ void addMetricProperty( + std::string sensorId; + if (dbus::utility::getNthStringFromPath(dbusSensor, 3, sensorId)) + { +- if (sensors::toReadingType(sensorId) == readingType) ++ if (groupName(sensorId) == group) + { + metricProperties.push_back(redfishSensor); + } +@@ -172,33 +183,37 @@ inline void requestRoutesMetricDefinition(App& app) + .methods(boost::beast::http::verb::get)( + [](const crow::Request&, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, +- const std::string& readingType) { +- if (!telemetry::isSensorIdSupported(readingType)) ++ const std::string& group) { ++ if (!telemetry::isSensorIdSupported(group)) + { + messages::resourceNotFound(asyncResp->res, +- "MetricDefinition", readingType); ++ "MetricDefinition", group); + return; + } + + asyncResp->res.jsonValue["MetricProperties"] = + nlohmann::json::array(); +- asyncResp->res.jsonValue["Id"] = readingType; +- asyncResp->res.jsonValue["Name"] = readingType; ++ asyncResp->res.jsonValue["Id"] = group; ++ asyncResp->res.jsonValue["Name"] = group; + asyncResp->res.jsonValue["@odata.id"] = +- telemetry::metricDefinitionUri + readingType; ++ telemetry::metricDefinitionUri + group; + asyncResp->res.jsonValue["@odata.type"] = + "#MetricDefinition.v1_0_3.MetricDefinition"; + asyncResp->res.jsonValue["MetricDataType"] = "Decimal"; + asyncResp->res.jsonValue["MetricType"] = "Numeric"; + asyncResp->res.jsonValue["IsLinear"] = true; + asyncResp->res.jsonValue["Implementation"] = "PhysicalSensor"; +- asyncResp->res.jsonValue["Units"] = +- sensors::toReadingUnits(readingType); ++ ++ std::string readingUnits = sensors::toReadingUnits(group); ++ if (!readingUnits.empty()) ++ { ++ asyncResp->res.jsonValue["Units"] = readingUnits; ++ } + + utils::getChassisNames( +- [asyncResp, readingType]( +- boost::system::error_code ec, +- const std::vector<std::string>& chassisNames) { ++ [asyncResp, ++ group](boost::system::error_code ec, ++ const std::vector<std::string>& chassisNames) { + if (ec) + { + messages::internalError(asyncResp->res); +@@ -208,10 +223,10 @@ inline void requestRoutesMetricDefinition(App& app) + } + + auto handleRetrieveUriToDbusMap = +- [asyncResp, readingType]( +- const boost::beast::http::status status, +- const boost::container::flat_map< +- std::string, std::string>& uriToDbus) { ++ [asyncResp, ++ group](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 +@@ -221,8 +236,8 @@ inline void requestRoutesMetricDefinition(App& app) + messages::internalError(asyncResp->res); + return; + } +- telemetry::addMetricProperty( +- *asyncResp, readingType, uriToDbus); ++ telemetry::addMetricProperty(*asyncResp, group, ++ uriToDbus); + }; + + for (const std::string& chassisName : chassisNames) +-- +2.25.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README index ea6ac73bd..cd15a815c 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README @@ -3,13 +3,22 @@ Until change is integrated they will be manually merged here to enable feature i Current revisions: - Add support for MetricDefinition scheme - https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/33363/80 + https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/33363/89 - Sync Telmetry service with EventService - https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/38798/31 + https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/38798/36 - LogService field, actual implementation will be upstreamed with triggers feature file://telemetry/0003-Revert-Remove-LogService-from-TelemetryService.patch - Event service fix for Context field file://telemetry/0004-event-service-fix-added-Context-field-to-response.patch + +- Switched bmcweb to use new telemetry service API + https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/44270/4 + +- Add support for MetricDefinition property in MetricReport + https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/44512/8 + +- Generalize ReadingType in MetricDefinition + file://telemetry/0007-Generalize-ReadingType-in-MetricDefinition.patch
\ No newline at end of file diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0001-Revert-Disable-nbd-proxy-from-the-build.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0001-Revert-Disable-nbd-proxy-from-the-build.patch index 3e3f69d1c..d41383836 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0001-Revert-Disable-nbd-proxy-from-the-build.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0001-Revert-Disable-nbd-proxy-from-the-build.patch @@ -1,32 +1,35 @@ -From 95f002dc969d7d6d64dbf2ee0db7dc1c1c6a9173 Mon Sep 17 00:00:00 2001 -From: Przemyslaw Czarnowski <przemyslaw.hawrylewicz.czarnowski@intel.com> -Date: Thu, 18 Mar 2021 11:30:28 +0100 +From 3ee7fe58b2acec0a6ae4eabad91a9dd609268870 Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> +Date: Wed, 14 Jul 2021 09:04:42 +0000 Subject: [PATCH] Revert "Disable nbd proxy from the build" NBD Proxy has been disabled upstream. Reenable as we use it for Virtual Media This reverts commit efb8062c306474942bc94f15d748b2eb0b58fbb6. + +Change-Id: I19a88b30c1074dd376f2df8f5668245b638b881f --- - meson.build | 2 +- - meson_options.txt | 9 +-------- - 2 files changed, 2 insertions(+), 9 deletions(-) + meson.build | 3 ++- + meson_options.txt | 10 ++-------- + 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/meson.build b/meson.build -index 66a066b..cef0a49 100644 +index bdc514b..19364a8 100644 --- a/meson.build +++ b/meson.build -@@ -81,7 +81,7 @@ feature_map = { +@@ -78,7 +78,8 @@ feature_map = { + 'rest' : '-DBMCWEB_ENABLE_DBUS_REST', 'static-hosting' : '-DBMCWEB_ENABLE_STATIC_HOSTING', 'insecure-tftp-update' : '-DBMCWEB_INSECURE_ENABLE_REDFISH_FW_TFTP_UPDATE', - 'validate-unsecure-feature' : '-DBMCWEB_ENABLE_VALIDATION_UNSECURE_FEATURE', -#'vm-nbdproxy' : '-DBMCWEB_ENABLE_VM_NBDPROXY', ++'validate-unsecure-feature' : '-DBMCWEB_ENABLE_VALIDATION_UNSECURE_FEATURE', +'vm-nbdproxy' : '-DBMCWEB_ENABLE_VM_NBDPROXY', 'vm-websocket' : '-DBMCWEB_ENABLE_VM_WEBSOCKET', } diff --git a/meson_options.txt b/meson_options.txt -index 9611631..7ee3ebb 100644 +index 0ab31b8..ea0f2fc 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -3,14 +3,7 @@ option('yocto-deps', type: 'feature', value: 'disabled', description : 'Use YOCT @@ -45,6 +48,14 @@ index 9611631..7ee3ebb 100644 option('rest', type : 'feature', value : 'enabled', description : '''Enable Phosphor REST (D-Bus) APIs. Paths directly map Phosphor D-Bus object paths, for example, \'/xyz/openbmc_project/logging/entry/enumerate\'. See https://github.com/openbmc/docs/blob/master/rest-api.md.''') option('redfish', type : 'feature',value : 'enabled', description: 'Enable Redfish APIs. Paths are under \'/redfish/v1/\'. See https://github.com/openbmc/bmcweb/blob/master/DEVELOPING.md#redfish.') option('host-serial-socket', type : 'feature', value : 'enabled', description : 'Enable host serial console WebSocket. Path is \'/console0\'. See https://github.com/openbmc/docs/blob/master/console.md.') +@@ -37,6 +30,7 @@ option ('https_port', type : 'integer', min : 1, max : 65535, value : 443, descr + # the implications of doing so.In general, enabling these options will cause security + # problems of varying degrees + ++option ('validate-unsecure-feature', type : 'feature', value : 'disabled', description : '''Enables unsecure features required by validation. Note: mustbe turned off for production images.''') + option ('insecure-disable-csrf', type : 'feature', value : 'disabled', description : 'Disable CSRF prevention checks.Should be set to false for production systems.') + option ('insecure-disable-ssl', type : 'feature', value : 'disabled', description : 'Disable SSL ports. Should be set to false for production systems.') + option ('insecure-disable-auth', type : 'feature', value : 'disabled', description : 'Disable authentication on all ports. Should be set to false for production systems') -- -2.26.2 +2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0002-bmcweb-handle-device-or-resource-busy-exception.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0002-bmcweb-handle-device-or-resource-busy-exception.patch index 01c1c858c..e267dc60f 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0002-bmcweb-handle-device-or-resource-busy-exception.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0002-bmcweb-handle-device-or-resource-busy-exception.patch @@ -1,6 +1,6 @@ -From 76480c6a5b1708113f28aecab32a85984371243c Mon Sep 17 00:00:00 2001 -From: Karol Wachowski <karol.wachowski@intel.com> -Date: Fri, 10 Jul 2020 09:54:06 +0000 +From bbb69d73ca8b74d34fa250813123de4274d5327b Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> +Date: Fri, 23 Jul 2021 12:07:02 +0000 Subject: [PATCH] bmcweb handle device or resource busy exception Use async_method_call_timed() for mount/unmount dbus oprations. @@ -21,23 +21,23 @@ Tested: Verified that after mounting non-existing HTTPS resource Signed-off-by: Karol Wachowski <karol.wachowski@intel.com> Change-Id: Ica62c34db0cce24c4c6169fc661edfde49e948d0 --- - redfish-core/lib/virtual_media.hpp | 144 ++++++++++++++++++++++------- - 1 file changed, 110 insertions(+), 34 deletions(-) + redfish-core/lib/virtual_media.hpp | 142 +++++++++++++++++++++-------- + 1 file changed, 105 insertions(+), 37 deletions(-) diff --git a/redfish-core/lib/virtual_media.hpp b/redfish-core/lib/virtual_media.hpp -index 95a8881..188248a 100644 +index 6e69f20..7fcbf73 100644 --- a/redfish-core/lib/virtual_media.hpp +++ b/redfish-core/lib/virtual_media.hpp -@@ -24,6 +24,8 @@ - #include <account_service.hpp> +@@ -26,6 +26,8 @@ #include <boost/url/url_view.hpp> + #include <registries/privilege_registry.hpp> +#include <chrono> + namespace redfish - { -@@ -160,6 +162,26 @@ static void vmParseInterfaceObject(const DbusInterfaceType& interface, + /** +@@ -162,6 +164,26 @@ inline void } } @@ -64,156 +64,151 @@ index 95a8881..188248a 100644 /** * @brief Fill template for Virtual Media Item. */ -@@ -856,22 +878,54 @@ class VirtualMediaActionInsertMedia : public Node - } +@@ -712,22 +734,57 @@ inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + } - crow::connections::systemBus->async_method_call( -- [asyncResp, secretPipe](const boost::system::error_code ec, -- bool success) { -+ [asyncResp, service, name, imageUrl, rw, unixFd, -+ secretPipe](const boost::system::error_code ec, -+ const std::variant<int> timeoutProperty) { - if (ec) - { - BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; - messages::internalError(asyncResp->res); -+ return; - } -- else if (!success) + crow::connections::systemBus->async_method_call( +- [asyncResp, secretPipe](const boost::system::error_code ec, +- bool success) { ++ [asyncResp, service, name, imageUrl, rw, unixFd, ++ secretPipe](const boost::system::error_code ec, ++ const std::variant<int> timeoutProperty) { + if (ec) + { + BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; + messages::internalError(asyncResp->res); ++ return; + } +- else if (!success) + -+ auto timeout = vmParseTimeoutProperty(timeoutProperty); -+ if (timeout == std::nullopt) - { -- BMCWEB_LOG_ERROR << "Service responded with error"; -- messages::generalError(asyncResp->res); -+ BMCWEB_LOG_ERROR << "Timeout property is empty."; -+ messages::internalError(asyncResp->res); -+ return; - } ++ auto timeout = vmParseTimeoutProperty(timeoutProperty); ++ if (timeout == std::nullopt) + { +- BMCWEB_LOG_ERROR << "Service responded with error"; +- messages::generalError(asyncResp->res); ++ BMCWEB_LOG_ERROR << "Timeout property is empty."; ++ messages::internalError(asyncResp->res); ++ return; + } + -+ crow::connections::systemBus->async_method_call_timed( -+ [asyncResp, secretPipe](const boost::system::error_code ec, -+ bool success) { -+ if (ec) ++ crow::connections::systemBus->async_method_call_timed( ++ [asyncResp, secretPipe](const boost::system::error_code ec, ++ bool success) { ++ if (ec) ++ { ++ BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; ++ if (ec == boost::system::errc::device_or_resource_busy) + { -+ BMCWEB_LOG_ERROR << "Bad D-Bus request error: " -+ << ec; -+ if (ec == -+ boost::system::errc::device_or_resource_busy) -+ { -+ messages::resourceInUse(asyncResp->res); -+ } -+ else -+ { -+ messages::internalError(asyncResp->res); -+ } ++ messages::resourceInUse(asyncResp->res); + } -+ else if (!success) ++ else if (ec == boost::system::errc::permission_denied) + { -+ BMCWEB_LOG_ERROR << "Service responded with error"; -+ messages::generalError(asyncResp->res); ++ messages::accessDenied(asyncResp->res, ++ "VirtualMedia.Insert"); + } -+ }, -+ service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, -+ "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", -+ *timeout, imageUrl, rw, unixFd); - }, - service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, -- "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw, -- unixFd); -+ "org.freedesktop.DBus.Properties", "Get", -+ "xyz.openbmc_project.VirtualMedia.MountPoint", "Timeout"); - } - }; ++ else ++ { ++ messages::internalError(asyncResp->res); ++ } ++ } ++ else if (!success) ++ { ++ BMCWEB_LOG_ERROR << "Service responded with error "; ++ messages::generalError(asyncResp->res); ++ } ++ }, ++ service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, ++ "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", *timeout, ++ imageUrl, rw, unixFd); + }, + service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, +- "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw, +- unixFd); ++ "org.freedesktop.DBus.Properties", "Get", ++ "xyz.openbmc_project.VirtualMedia.MountPoint", "Timeout"); + } -@@ -1003,38 +1057,60 @@ class VirtualMediaActionEjectMedia : public Node - const std::string& service, const std::string& name, - bool legacy) - { -- -- // Legacy mount requires parameter with image -+ std::string objectPath = "/xyz/openbmc_project/VirtualMedia/"; -+ std::string ifaceName = "xyz.openbmc_project.VirtualMedia"; - if (legacy) - { -- 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; -- } -- }, -- service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, -- "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount"); -+ objectPath += "Legacy/"; -+ ifaceName += ".Legacy"; - } -- else // proxy -+ else - { -- crow::connections::systemBus->async_method_call( -- [asyncResp](const boost::system::error_code ec) { -- if (ec) -- { -- BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; + /** +@@ -739,38 +796,49 @@ inline void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& service, const std::string& name, + bool legacy) + { ++ const std::string vmMode = legacy ? "Legacy" : "Proxy"; ++ const std::string objectPath = ++ "/xyz/openbmc_project/VirtualMedia/" + vmMode + "/" + name; ++ const std::string ifaceName = "xyz.openbmc_project.VirtualMedia." + vmMode; + +- // Legacy mount requires parameter with image +- if (legacy) +- { +- 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; -- } -- }, -- service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name, -- "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount"); -+ objectPath += "Proxy/"; -+ ifaceName += ".Proxy"; - } -+ objectPath += name; -+ -+ crow::connections::systemBus->async_method_call( -+ [asyncResp, service, name, objectPath, -+ ifaceName](const boost::system::error_code ec, -+ const std::variant<int> timeoutProperty) { -+ if (ec) -+ { -+ BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ -+ auto timeout = vmParseTimeoutProperty(timeoutProperty); -+ if (timeout == std::nullopt) -+ { -+ BMCWEB_LOG_ERROR << "Timeout property is empty."; -+ messages::internalError(asyncResp->res); -+ return; -+ } -+ crow::connections::systemBus->async_method_call_timed( -+ [asyncResp](const boost::system::error_code ec) { -+ if (ec) +- messages::internalError(asyncResp->res); +- return; +- } +- }, +- service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, +- "xyz.openbmc_project.VirtualMedia.Legacy", "Unmount"); +- } +- else // proxy +- { +- crow::connections::systemBus->async_method_call( +- [asyncResp](const boost::system::error_code ec) { +- if (ec) +- { +- BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; ++ crow::connections::systemBus->async_method_call( ++ [asyncResp, service, name, objectPath, ++ ifaceName](const boost::system::error_code ec, ++ const std::variant<int> timeoutProperty) { ++ if (ec) ++ { ++ BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; ++ messages::internalError(asyncResp->res); ++ return; ++ } + +- messages::internalError(asyncResp->res); +- return; +- } +- }, +- service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name, +- "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount"); +- } ++ auto timeout = vmParseTimeoutProperty(timeoutProperty); ++ if (timeout == std::nullopt) ++ { ++ BMCWEB_LOG_ERROR << "Timeout property is empty."; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ crow::connections::systemBus->async_method_call_timed( ++ [asyncResp](const boost::system::error_code ec) { ++ if (ec) ++ { ++ BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; ++ if (ec == boost::system::errc::device_or_resource_busy) + { -+ BMCWEB_LOG_ERROR << "Bad D-Bus request error: " -+ << ec; -+ if (ec == -+ boost::system::errc::device_or_resource_busy) -+ { -+ messages::resourceInUse(asyncResp->res); -+ } -+ else -+ { -+ messages::internalError(asyncResp->res); -+ } -+ return; ++ messages::resourceInUse(asyncResp->res); + } -+ }, -+ service, objectPath, ifaceName, "Unmount", *timeout); -+ }, -+ service, objectPath, "org.freedesktop.DBus.Properties", "Get", -+ "xyz.openbmc_project.VirtualMedia.MountPoint", "Timeout"); - } - }; ++ else ++ { ++ messages::internalError(asyncResp->res); ++ } ++ return; ++ } ++ }, ++ service, objectPath, ifaceName, "Unmount", *timeout); ++ }, ++ service, objectPath, "org.freedesktop.DBus.Properties", "Get", ++ "xyz.openbmc_project.VirtualMedia.MountPoint", "Timeout"); + } + inline void requestNBDVirtualMediaRoutes(App& app) -- -2.17.1 +2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0004-Invalid-status-code-from-InsertMedia-REST-methods.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0004-Invalid-status-code-from-InsertMedia-REST-methods.patch index 3a9e67217..b29082dce 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0004-Invalid-status-code-from-InsertMedia-REST-methods.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0004-Invalid-status-code-from-InsertMedia-REST-methods.patch @@ -1,8 +1,8 @@ -From 805641a2d189da9befc05168f51cef76da1ba326 Mon Sep 17 00:00:00 2001 -From: Alicja Rybak <alicja.rybak@intel.com> -Date: Tue, 20 Apr 2021 16:32:37 +0200 -Subject: [PATCH] Invalid status code from InsertMedia REST methods GET, - PUT, DELETE, PATCH in proxy mode +From 95f7ca477a8353fa7b99f463de9ee310dda13735 Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> +Date: Thu, 1 Jul 2021 10:08:27 +0000 +Subject: [PATCH] Invalid status code from InsertMedia REST methods GET, PUT, + DELETE, PATCH in proxy mode Add handlers for GET, PUT, DELETE, PATCH method and function that checks which mode is used and set suitable status code: @@ -11,175 +11,156 @@ Not allowed for Legacy and Not found for Proxy. Change-Id: Ib4c0a3e9a2a8853caa74c59239d9fcfed99c5e8b Signed-off-by: Alicja Rybak <alicja.rybak@intel.com> --- - redfish-core/lib/virtual_media.hpp | 155 +++++++++++++++++++++++++++++ - 1 file changed, 155 insertions(+) + redfish-core/lib/virtual_media.hpp | 129 +++++++++++++++++++++++++++++ + 1 file changed, 129 insertions(+) diff --git a/redfish-core/lib/virtual_media.hpp b/redfish-core/lib/virtual_media.hpp -index aa7c639..3e28164 100644 +index a834c69..186c04b 100644 --- a/redfish-core/lib/virtual_media.hpp +++ b/redfish-core/lib/virtual_media.hpp -@@ -548,6 +548,161 @@ class VirtualMediaActionInsertMedia : public Node - return true; - } +@@ -28,6 +28,109 @@ -+ /** -+ * @brief Function checks if insert media request is Legacy or Proxy type -+ * and sets suitable response code for unsupported REST method. -+ * -+ */ -+ void CheckProxyMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp, -+ const crow::Request& req, -+ const std::vector<std::string>& params) + namespace redfish + { ++ ++/** ++ * @brief Function checks if insert media request is Legacy or Proxy type ++ * and sets suitable response code for unsupported REST method. ++ * ++ */ ++void CheckProxyMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp, ++ const crow::Request& req, const std::string& name, ++ const std::string& resName) ++{ ++ if (name != "bmc") + { -+ if (params.size() != 2) -+ { -+ messages::internalError(aResp->res); -+ return; -+ } -+ -+ // take resource name from URL -+ const std::string& resName = params[1]; -+ -+ if (params[0] != "bmc") -+ { -+ messages::resourceNotFound(aResp->res, "VirtualMedia.Insert", -+ resName); -+ -+ return; -+ } -+ -+ crow::connections::systemBus->async_method_call( -+ [this, aResp{std::move(aResp)}, req, -+ resName](const boost::system::error_code ec, -+ const GetObjectType& getObjectType) { -+ if (ec) -+ { -+ BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " -+ << ec; -+ aResp->res.result(boost::beast::http::status::not_found); ++ messages::resourceNotFound(aResp->res, "VirtualMedia.Insert", resName); + -+ return; -+ } -+ std::string service = getObjectType.begin()->first; -+ BMCWEB_LOG_DEBUG << "GetObjectType: " << service; ++ return; ++ } + -+ crow::connections::systemBus->async_method_call( -+ [this, service, resName, req, -+ aResp{aResp}](const boost::system::error_code ec, -+ ManagedObjectType& subtree) { -+ if (ec) ++ crow::connections::systemBus->async_method_call( ++ [aResp, req, resName](const boost::system::error_code ec, ++ const GetObjectType& getObjectType) { ++ if (ec) ++ { ++ BMCWEB_LOG_ERROR << "ObjectMapper::GetObject call failed: " ++ << ec; ++ aResp->res.result(boost::beast::http::status::not_found); ++ ++ return; ++ } ++ std::string service = getObjectType.begin()->first; ++ BMCWEB_LOG_DEBUG << "GetObjectType: " << service; ++ ++ crow::connections::systemBus->async_method_call( ++ [service, resName, req, ++ aResp](const boost::system::error_code ec, ++ ManagedObjectType& subtree) { ++ if (ec) ++ { ++ BMCWEB_LOG_DEBUG << "DBUS response error"; ++ ++ return; ++ } ++ ++ for (auto& item : subtree) ++ { ++ std::string thispath = item.first.filename(); ++ if (thispath.empty()) + { -+ BMCWEB_LOG_DEBUG << "DBUS response error"; ++ continue; ++ } + -+ return; ++ if (thispath != resName) ++ { ++ continue; + } + -+ for (auto& item : subtree) ++ auto mode = item.first.parent_path(); ++ auto type = mode.parent_path(); ++ if (mode.filename().empty() || type.filename().empty()) + { -+ std::string thispath = item.first.filename(); -+ if (thispath.empty()) -+ { -+ continue; -+ } -+ -+ if (thispath != resName) -+ { -+ continue; -+ } -+ -+ auto mode = item.first.parent_path(); -+ auto type = mode.parent_path(); -+ if (mode.filename().empty() || -+ type.filename().empty()) -+ { -+ continue; -+ } -+ -+ if (type.filename() != "VirtualMedia") -+ { -+ continue; -+ } -+ -+ // Check if dbus path is Legacy type -+ if (mode.filename() == "Legacy") -+ { -+ BMCWEB_LOG_DEBUG << "InsertMedia only allowed " -+ "with POST method " -+ "in legacy mode"; -+ aResp->res.result(boost::beast::http::status:: -+ method_not_allowed); -+ -+ return; -+ } -+ // Check if dbus path is Proxy type -+ if (mode.filename() == "Proxy") -+ { -+ // Not possible in proxy mode -+ BMCWEB_LOG_DEBUG << "InsertMedia not " -+ "allowed in proxy mode"; -+ aResp->res.result( -+ boost::beast::http::status::not_found); -+ -+ return; -+ } ++ continue; + } + -+ BMCWEB_LOG_DEBUG << "Parent item not found"; -+ aResp->res.result( -+ boost::beast::http::status::not_found); -+ }, -+ service, "/xyz/openbmc_project/VirtualMedia", -+ "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); -+ }, -+ "xyz.openbmc_project.ObjectMapper", -+ "/xyz/openbmc_project/object_mapper", -+ "xyz.openbmc_project.ObjectMapper", "GetObject", -+ "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); -+ } ++ if (type.filename() != "VirtualMedia") ++ { ++ continue; ++ } + -+ /** -+ * @brief Function handles GET method request. -+ */ -+ void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, -+ const crow::Request& req, -+ const std::vector<std::string>& params) override -+ { -+ CheckProxyMode(asyncResp, req, params); -+ } ++ // Check if dbus path is Legacy type ++ if (mode.filename() == "Legacy") ++ { ++ BMCWEB_LOG_DEBUG << "InsertMedia only allowed " ++ "with POST method " ++ "in legacy mode"; ++ aResp->res.result( ++ boost::beast::http::status::method_not_allowed); + -+ /** -+ * @brief Function handles PATCH method request. -+ */ -+ void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, -+ const crow::Request& req, -+ const std::vector<std::string>& params) override -+ { -+ CheckProxyMode(asyncResp, req, params); -+ } ++ return; ++ } ++ // Check if dbus path is Proxy type ++ if (mode.filename() == "Proxy") ++ { ++ // Not possible in proxy mode ++ BMCWEB_LOG_DEBUG << "InsertMedia not " ++ "allowed in proxy mode"; ++ aResp->res.result( ++ boost::beast::http::status::not_found); + -+ /** -+ * @brief Function handles PUT method request. -+ */ -+ void doPut(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, -+ const crow::Request& req, -+ const std::vector<std::string>& params) override -+ { -+ CheckProxyMode(asyncResp, req, params); -+ } ++ return; ++ } ++ } + -+ /** -+ * @brief Function handles DELETE method request. -+ */ -+ void doDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, -+ const crow::Request& req, -+ const std::vector<std::string>& params) override ++ BMCWEB_LOG_DEBUG << "Parent item not found"; ++ aResp->res.result(boost::beast::http::status::not_found); ++ }, ++ service, "/xyz/openbmc_project/VirtualMedia", ++ "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); ++ }, ++ "xyz.openbmc_project.ObjectMapper", ++ "/xyz/openbmc_project/object_mapper", ++ "xyz.openbmc_project.ObjectMapper", "GetObject", ++ "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); ++} ++ + /** + * @brief Function extracts transfer protocol name from URI. + */ +@@ -829,6 +932,32 @@ inline void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + + inline void requestNBDVirtualMediaRoutes(App& app) + { ++ BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/" ++ "VirtualMedia.InsertMedia") ++ .privileges({{"Login"}}) ++ .methods(boost::beast::http::verb::get)( ++ [](const crow::Request& req, ++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, ++ const std::string& name, const std::string& resName) { ++ CheckProxyMode(asyncResp, req, name, resName); ++ }); ++ ++ for (auto method : ++ {boost::beast::http::verb::patch, boost::beast::http::verb::put, ++ boost::beast::http::verb::delete_}) + { -+ CheckProxyMode(asyncResp, req, params); ++ BMCWEB_ROUTE(app, ++ "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/" ++ "VirtualMedia.InsertMedia") ++ .privileges({{"ConfigureManager"}}) ++ .methods(method)( ++ [](const crow::Request& req, ++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, ++ const std::string& name, const std::string& resName) { ++ CheckProxyMode(asyncResp, req, name, resName); ++ }); + } + - /** - * @brief Function handles POST method request. - * + BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/Actions/" + "VirtualMedia.InsertMedia") + .privileges({{"ConfigureManager"}}) -- -2.17.1 +2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0006-Bmcweb-handle-permission-denied-exception.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0006-Bmcweb-handle-permission-denied-exception.patch index efce3e72c..6ad7cf174 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0006-Bmcweb-handle-permission-denied-exception.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0006-Bmcweb-handle-permission-denied-exception.patch @@ -1,6 +1,6 @@ -From e7018ea9e3ad1a17e096aec3717a4764c3feac2e Mon Sep 17 00:00:00 2001 -From: Alicja Rybak <alicja.rybak@intel.com> -Date: Wed, 14 Apr 2021 16:26:59 +0200 +From 1d69a22d0ec1eddbe6d703d6824f413f6b68399e Mon Sep 17 00:00:00 2001 +From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> +Date: Thu, 1 Jul 2021 10:41:47 +0000 Subject: [PATCH] Bmcweb handle permission denied exception Add handling of permission denied exception (EPERM) that @@ -13,35 +13,25 @@ VirtualMedia returns EPERM, which bmcweb handles as 403 status code. Change-Id: Ibc18d5ec822c5072605b1fc4651389982002798b Signed-off-by: Alicja Rybak <alicja.rybak@intel.com> --- - redfish-core/lib/virtual_media.hpp | 8 ++++++++ - 1 file changed, 8 insertions(+) + redfish-core/lib/virtual_media.hpp | 5 +++++ + 1 file changed, 5 insertions(+) diff --git a/redfish-core/lib/virtual_media.hpp b/redfish-core/lib/virtual_media.hpp -index 4c475b7..8151ac0 100644 +index 186c04b..8e7c2e4 100644 --- a/redfish-core/lib/virtual_media.hpp +++ b/redfish-core/lib/virtual_media.hpp -@@ -1073,6 +1073,10 @@ class VirtualMediaActionInsertMedia : public Node - { - messages::resourceInUse(asyncResp->res); - } -+ else if (ec == boost::system::errc::permission_denied) -+ { -+ messages::accessDenied(asyncResp->res, "VirtualMedia.Insert"); -+ } - else - { - messages::internalError(asyncResp->res); -@@ -1267,6 +1271,10 @@ class VirtualMediaActionEjectMedia : public Node - { - messages::resourceInUse(asyncResp->res); - } -+ else if (ec == boost::system::errc::permission_denied) -+ { -+ messages::accessDenied(asyncResp->res, "VirtualMedia.Eject"); -+ } - else - { - messages::internalError(asyncResp->res); +@@ -917,6 +917,11 @@ inline void doVmAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + { + messages::resourceInUse(asyncResp->res); + } ++ else if (ec == boost::system::errc::permission_denied) ++ { ++ messages::accessDenied(asyncResp->res, ++ "VirtualMedia.Insert"); ++ } + else + { + messages::internalError(asyncResp->res); -- -2.17.1 +2.25.1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0008-Fix-VM-NBDPROXY-build-issue-with-AsyncResp.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0008-Fix-VM-NBDPROXY-build-issue-with-AsyncResp.patch deleted file mode 100644 index c188b2105..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0008-Fix-VM-NBDPROXY-build-issue-with-AsyncResp.patch +++ /dev/null @@ -1,37 +0,0 @@ -From d31d913a8c5dbacf6a36407532cf777852099ced Mon Sep 17 00:00:00 2001 -From: AppaRao Puli <apparao.puli@linux.intel.com> -Date: Sun, 2 May 2021 11:07:16 +0000 -Subject: [PATCH] Fix VM NBDPROXY build issue with AsyncResp - -8d1b46d7 moves bmcweb to using AsyncResp everywhere, and not have -each individual handler creating its own object. - -This commit fixes the build failure when enabling virtual media -compile flag(BMCWEB_ENABLE_VM_NBDPROXY). This is caused by above -mentioned recent change. - -Tested: - - Build is successful with enabled virtual media flag. - -Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com> -Change-Id: I363a41a08fae9dc05b3553695b96ffd26948f696 ---- - redfish-core/lib/virtual_media.hpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/redfish-core/lib/virtual_media.hpp b/redfish-core/lib/virtual_media.hpp -index 685ee5c..99542c4 100644 ---- a/redfish-core/lib/virtual_media.hpp -+++ b/redfish-core/lib/virtual_media.hpp -@@ -635,7 +635,7 @@ class VirtualMediaActionInsertMedia : public Node - } - - bool paramsValid = validateParams( -- asyncResp->res, imageUrl, inserted, -+ asyncResp, imageUrl, inserted, - transferMethod, transferProtocolType); - - if (paramsValid == false) --- -2.17.1 - |