simpleupdate: Move code around for future re-use
A lot of the existing code for the UpdateService path can be used for
SimpleUpdate. Move the common code into static functions so that both
paths can call them.
Tested:
Verified good path code update still works against UpdateService
Change-Id: Ie69b2bdc7b286b9d0596a2ca193810270a3f7dbb
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
index 9f16e1e..6b1b38c 100644
--- a/redfish-core/lib/update_service.hpp
+++ b/redfish-core/lib/update_service.hpp
@@ -28,6 +28,146 @@
static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateMatcher;
// Only allow one update at a time
static bool fwUpdateInProgress = false;
+// Timer for software available
+static std::unique_ptr<boost::asio::deadline_timer> fwAvailableTimer;
+
+static void cleanUp()
+{
+ fwUpdateInProgress = false;
+ fwUpdateMatcher = nullptr;
+}
+static void activateImage(const std::string &objPath,
+ const std::string &service)
+{
+ BMCWEB_LOG_DEBUG << "Activate image for " << objPath << " " << service;
+ crow::connections::systemBus->async_method_call(
+ [](const boost::system::error_code error_code) {
+ if (error_code)
+ {
+ BMCWEB_LOG_DEBUG << "error_code = " << error_code;
+ BMCWEB_LOG_DEBUG << "error msg = " << error_code.message();
+ }
+ },
+ service, objPath, "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Software.Activation", "RequestedActivation",
+ std::variant<std::string>(
+ "xyz.openbmc_project.Software.Activation.RequestedActivations."
+ "Active"));
+}
+static void softwareInterfaceAdded(std::shared_ptr<AsyncResp> asyncResp,
+ sdbusplus::message::message &m)
+{
+ std::vector<std::pair<
+ std::string,
+ std::vector<std::pair<std::string, std::variant<std::string>>>>>
+ interfacesProperties;
+
+ sdbusplus::message::object_path objPath;
+
+ m.read(objPath, interfacesProperties);
+
+ BMCWEB_LOG_DEBUG << "obj path = " << objPath.str;
+ for (auto &interface : interfacesProperties)
+ {
+ BMCWEB_LOG_DEBUG << "interface = " << interface.first;
+
+ if (interface.first == "xyz.openbmc_project.Software.Activation")
+ {
+ // Found our interface, disable callbacks
+ fwUpdateMatcher = nullptr;
+
+ // Retrieve service and activate
+ crow::connections::systemBus->async_method_call(
+ [objPath, asyncResp](
+ const boost::system::error_code error_code,
+ const std::vector<std::pair<
+ std::string, std::vector<std::string>>> &objInfo) {
+ if (error_code)
+ {
+ BMCWEB_LOG_DEBUG << "error_code = " << error_code;
+ BMCWEB_LOG_DEBUG << "error msg = "
+ << error_code.message();
+ messages::internalError(asyncResp->res);
+ cleanUp();
+ return;
+ }
+ // Ensure we only got one service back
+ if (objInfo.size() != 1)
+ {
+ BMCWEB_LOG_ERROR << "Invalid Object Size "
+ << objInfo.size();
+ messages::internalError(asyncResp->res);
+ cleanUp();
+ return;
+ }
+ // cancel timer only when
+ // xyz.openbmc_project.Software.Activation interface
+ // is added
+ fwAvailableTimer = nullptr;
+
+ activateImage(objPath.str, objInfo[0].first);
+ redfish::messages::success(asyncResp->res);
+ fwUpdateInProgress = false;
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetObject", objPath.str,
+ std::array<const char *, 1>{
+ "xyz.openbmc_project.Software.Activation"});
+ }
+ }
+}
+
+static void monitorForSoftwareAvailable(std::shared_ptr<AsyncResp> asyncResp,
+ const crow::Request &req)
+{
+ // Only allow one FW update at a time
+ if (fwUpdateInProgress != false)
+ {
+ asyncResp->res.addHeader("Retry-After", "30");
+ messages::serviceTemporarilyUnavailable(asyncResp->res, "30");
+ return;
+ }
+
+ fwAvailableTimer = std::make_unique<boost::asio::deadline_timer>(
+ *req.ioService, boost::posix_time::seconds(5));
+
+ fwAvailableTimer->expires_from_now(boost::posix_time::seconds(5));
+
+ fwAvailableTimer->async_wait(
+ [asyncResp](const boost::system::error_code &ec) {
+ cleanUp();
+ if (ec == boost::asio::error::operation_aborted)
+ {
+ // expected, we were canceled before the timer completed.
+ return;
+ }
+ BMCWEB_LOG_ERROR
+ << "Timed out waiting for firmware object being created";
+ BMCWEB_LOG_ERROR
+ << "FW image may has already been uploaded to server";
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "Async_wait failed" << ec;
+ return;
+ }
+
+ redfish::messages::internalError(asyncResp->res);
+ });
+
+ auto callback = [asyncResp](sdbusplus::message::message &m) {
+ BMCWEB_LOG_DEBUG << "Match fired";
+ softwareInterfaceAdded(asyncResp, m);
+ };
+
+ fwUpdateInProgress = true;
+
+ fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
+ *crow::connections::systemBus,
+ "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
+ "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
+ callback);
+}
class UpdateService : public Node
{
@@ -61,153 +201,16 @@
{"@odata.id", "/redfish/v1/UpdateService/FirmwareInventory"}};
res.end();
}
- static void cleanUp()
- {
- fwUpdateInProgress = false;
- fwUpdateMatcher = nullptr;
- }
- static void activateImage(const std::string &objPath,
- const std::string &service)
- {
- BMCWEB_LOG_DEBUG << "Activate image for " << objPath << " " << service;
- crow::connections::systemBus->async_method_call(
- [](const boost::system::error_code error_code) {
- if (error_code)
- {
- BMCWEB_LOG_DEBUG << "error_code = " << error_code;
- BMCWEB_LOG_DEBUG << "error msg = " << error_code.message();
- }
- },
- service, objPath, "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Software.Activation", "RequestedActivation",
- std::variant<std::string>(
- "xyz.openbmc_project.Software.Activation.RequestedActivations."
- "Active"));
- }
- static void softwareInterfaceAdded(std::shared_ptr<AsyncResp> asyncResp,
- boost::asio::deadline_timer &timeout,
- sdbusplus::message::message &m)
- {
- std::vector<std::pair<
- std::string,
- std::vector<std::pair<std::string, std::variant<std::string>>>>>
- interfacesProperties;
- sdbusplus::message::object_path objPath;
-
- m.read(objPath, interfacesProperties);
-
- BMCWEB_LOG_DEBUG << "obj path = " << objPath.str;
- for (auto &interface : interfacesProperties)
- {
- BMCWEB_LOG_DEBUG << "interface = " << interface.first;
-
- if (interface.first == "xyz.openbmc_project.Software.Activation")
- {
- // Found our interface, disable callbacks
- fwUpdateMatcher = nullptr;
-
- // Retrieve service and activate
- crow::connections::systemBus->async_method_call(
- [objPath, asyncResp, &timeout](
- const boost::system::error_code error_code,
- const std::vector<std::pair<
- std::string, std::vector<std::string>>> &objInfo) {
- if (error_code)
- {
- BMCWEB_LOG_DEBUG << "error_code = " << error_code;
- BMCWEB_LOG_DEBUG << "error msg = "
- << error_code.message();
- messages::internalError(asyncResp->res);
- cleanUp();
- return;
- }
- // Ensure we only got one service back
- if (objInfo.size() != 1)
- {
- BMCWEB_LOG_ERROR << "Invalid Object Size "
- << objInfo.size();
- messages::internalError(asyncResp->res);
- cleanUp();
- return;
- }
- // cancel timer only when
- // xyz.openbmc_project.Software.Activation interface
- // is added
- boost::system::error_code ec;
- timeout.cancel(ec);
- if (ec)
- {
- BMCWEB_LOG_ERROR << "error canceling timer " << ec;
- }
- UpdateService::activateImage(objPath.str,
- objInfo[0].first);
- redfish::messages::success(asyncResp->res);
- fwUpdateInProgress = false;
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetObject",
- objPath.str,
- std::array<const char *, 1>{
- "xyz.openbmc_project.Software.Activation"});
- }
- }
- }
void doPost(crow::Response &res, const crow::Request &req,
const std::vector<std::string> ¶ms) override
{
BMCWEB_LOG_DEBUG << "doPost...";
- // Only allow one FW update at a time
- if (fwUpdateInProgress != false)
- {
- res.addHeader("Retry-After", "30");
- messages::serviceTemporarilyUnavailable(res, "30");
- res.end();
- return;
- }
-
- // Make this const static so it survives outside this method
- static boost::asio::deadline_timer timeout(
- *req.ioService, boost::posix_time::seconds(5));
-
- timeout.expires_from_now(boost::posix_time::seconds(5));
-
- timeout.async_wait([&res](const boost::system::error_code &ec) {
- cleanUp();
- if (ec == boost::asio::error::operation_aborted)
- {
- // expected, we were canceled before the timer completed.
- return;
- }
- BMCWEB_LOG_ERROR
- << "Timed out waiting for firmware object being created";
- BMCWEB_LOG_ERROR
- << "FW image may has already been uploaded to server";
- if (ec)
- {
- BMCWEB_LOG_ERROR << "Async_wait failed" << ec;
- return;
- }
-
- redfish::messages::internalError(res);
- res.end();
- });
-
std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
- auto callback = [asyncResp](sdbusplus::message::message &m) {
- BMCWEB_LOG_DEBUG << "Match fired";
- softwareInterfaceAdded(asyncResp, timeout, m);
- };
- fwUpdateInProgress = true;
-
- fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
- *crow::connections::systemBus,
- "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
- "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
- callback);
+ // Setup callback for when new software detected
+ monitorForSoftwareAvailable(asyncResp, req);
std::string filepath(
"/tmp/images/" +