updateservice: refactor task creation
Refactor task creation into a separate function so it can be used from
different places in code. The new usage of this function will be from
start update interface based flow. More details refer to -
https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/65738
https://gerrit.openbmc.org/c/openbmc/docs/+/65739
Tested: Firmware update using curl.
Change-Id: I5e8a0ab98f49657178ee733fa4d34fbf40a7b1f3
Signed-off-by: Jagpal Singh Gill <paligill@gmail.com>
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
index f66fe46..81534f9 100644
--- a/redfish-core/lib/update_service.hpp
+++ b/redfish-core/lib/update_service.hpp
@@ -40,6 +40,7 @@
#include <array>
#include <filesystem>
+#include <functional>
#include <memory>
#include <optional>
#include <string>
@@ -85,6 +86,121 @@
});
}
+inline bool handleCreateTask(const boost::system::error_code& ec2,
+ sdbusplus::message_t& msg,
+ const std::shared_ptr<task::TaskData>& taskData)
+{
+ if (ec2)
+ {
+ return task::completed;
+ }
+
+ std::string iface;
+ dbus::utility::DBusPropertiesMap values;
+
+ std::string index = std::to_string(taskData->index);
+ msg.read(iface, values);
+
+ if (iface == "xyz.openbmc_project.Software.Activation")
+ {
+ const std::string* state = nullptr;
+ for (const auto& property : values)
+ {
+ if (property.first == "Activation")
+ {
+ state = std::get_if<std::string>(&property.second);
+ if (state == nullptr)
+ {
+ taskData->messages.emplace_back(messages::internalError());
+ return task::completed;
+ }
+ }
+ }
+
+ if (state == nullptr)
+ {
+ return !task::completed;
+ }
+
+ if (state->ends_with("Invalid") || state->ends_with("Failed"))
+ {
+ taskData->state = "Exception";
+ taskData->status = "Warning";
+ taskData->messages.emplace_back(messages::taskAborted(index));
+ return task::completed;
+ }
+
+ if (state->ends_with("Staged"))
+ {
+ taskData->state = "Stopping";
+ taskData->messages.emplace_back(messages::taskPaused(index));
+
+ // its staged, set a long timer to
+ // allow them time to complete the
+ // update (probably cycle the
+ // system) if this expires then
+ // task will be canceled
+ taskData->extendTimer(std::chrono::hours(5));
+ return !task::completed;
+ }
+
+ if (state->ends_with("Active"))
+ {
+ taskData->messages.emplace_back(messages::taskCompletedOK(index));
+ taskData->state = "Completed";
+ return task::completed;
+ }
+ }
+ else if (iface == "xyz.openbmc_project.Software.ActivationProgress")
+ {
+ const uint8_t* progress = nullptr;
+ for (const auto& property : values)
+ {
+ if (property.first == "Progress")
+ {
+ progress = std::get_if<uint8_t>(&property.second);
+ if (progress == nullptr)
+ {
+ taskData->messages.emplace_back(messages::internalError());
+ return task::completed;
+ }
+ }
+ }
+
+ if (progress == nullptr)
+ {
+ return !task::completed;
+ }
+ taskData->percentComplete = *progress;
+ taskData->messages.emplace_back(
+ messages::taskProgressChanged(index, *progress));
+
+ // if we're getting status updates it's
+ // still alive, update timer
+ taskData->extendTimer(std::chrono::minutes(5));
+ }
+
+ // as firmware update often results in a
+ // reboot, the task may never "complete"
+ // unless it is an error
+
+ return !task::completed;
+}
+
+inline void createTask(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ task::Payload&& payload,
+ const sdbusplus::message::object_path& objPath)
+{
+ std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
+ std::bind_front(handleCreateTask),
+ "type='signal',interface='org.freedesktop.DBus.Properties',"
+ "member='PropertiesChanged',path='" +
+ objPath.str + "'");
+ task->startTimer(std::chrono::minutes(5));
+ task->populateResp(asyncResp->res);
+ task->payload.emplace(std::move(payload));
+}
+
// Note that asyncResp can be either a valid pointer or nullptr. If nullptr
// then no asyncResp updates will occur
static void
@@ -144,125 +260,7 @@
activateImage(objPath.str, objInfo[0].first);
if (asyncResp)
{
- std::shared_ptr<task::TaskData> task =
- task::TaskData::createTask(
- [](const boost::system::error_code& ec2,
- sdbusplus::message_t& msg,
- const std::shared_ptr<task::TaskData>&
- taskData) {
- if (ec2)
- {
- return task::completed;
- }
-
- std::string iface;
- dbus::utility::DBusPropertiesMap values;
-
- std::string index = std::to_string(taskData->index);
- msg.read(iface, values);
-
- if (iface == "xyz.openbmc_project.Software.Activation")
- {
- const std::string* state = nullptr;
- for (const auto& property : values)
- {
- if (property.first == "Activation")
- {
- state = std::get_if<std::string>(
- &property.second);
- if (state == nullptr)
- {
- taskData->messages.emplace_back(
- messages::internalError());
- return task::completed;
- }
- }
- }
-
- if (state == nullptr)
- {
- return !task::completed;
- }
-
- if (state->ends_with("Invalid") ||
- state->ends_with("Failed"))
- {
- taskData->state = "Exception";
- taskData->status = "Warning";
- taskData->messages.emplace_back(
- messages::taskAborted(index));
- return task::completed;
- }
-
- if (state->ends_with("Staged"))
- {
- taskData->state = "Stopping";
- taskData->messages.emplace_back(
- messages::taskPaused(index));
-
- // its staged, set a long timer to
- // allow them time to complete the
- // update (probably cycle the
- // system) if this expires then
- // task will be canceled
- taskData->extendTimer(std::chrono::hours(5));
- return !task::completed;
- }
-
- if (state->ends_with("Active"))
- {
- taskData->messages.emplace_back(
- messages::taskCompletedOK(index));
- taskData->state = "Completed";
- return task::completed;
- }
- }
- else if (
- iface ==
- "xyz.openbmc_project.Software.ActivationProgress")
- {
- const uint8_t* progress = nullptr;
- for (const auto& property : values)
- {
- if (property.first == "Progress")
- {
- progress =
- std::get_if<uint8_t>(&property.second);
- if (progress == nullptr)
- {
- taskData->messages.emplace_back(
- messages::internalError());
- return task::completed;
- }
- }
- }
-
- if (progress == nullptr)
- {
- return !task::completed;
- }
- taskData->percentComplete = *progress;
- taskData->messages.emplace_back(
- messages::taskProgressChanged(index,
- *progress));
-
- // if we're getting status updates it's
- // still alive, update timer
- taskData->extendTimer(std::chrono::minutes(5));
- }
-
- // as firmware update often results in a
- // reboot, the task may never "complete"
- // unless it is an error
-
- return !task::completed;
- },
- "type='signal',interface='org.freedesktop.DBus.Properties',"
- "member='PropertiesChanged',path='" +
- objPath.str + "'");
- task->startTimer(std::chrono::minutes(5));
- task->populateResp(asyncResp->res);
- task->payload.emplace(std::move(payload));
+ createTask(asyncResp, std::move(payload), objPath);
}
fwUpdateInProgress = false;
});