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;
             });