task: add fwupdate support

This adds firmware update task service support. It adds
a match and updates the task value when the interface
changes.

Tested: On successful fwupdate task was created and
updated correctly. On failed fwupdate the status went
to failed.

Change-Id: Id12cc5d5270e8e45498b665e78601c5c30775323
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index 09602fb..ca9604b 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -1878,8 +1878,9 @@
                     if (!err)
                     {
                         taskData->messages.emplace_back(messages::success());
+                        taskData->status = "Completed";
                     }
-                    return true;
+                    return task::completed;
                 },
                 "type='signal',interface='org.freedesktop.DBus.Properties',"
                 "member='PropertiesChanged',arg0namespace='com.intel."
diff --git a/redfish-core/lib/task.hpp b/redfish-core/lib/task.hpp
index 12425c1..e95eb2e 100644
--- a/redfish-core/lib/task.hpp
+++ b/redfish-core/lib/task.hpp
@@ -30,6 +30,8 @@
 
 static std::deque<std::shared_ptr<struct TaskData>> tasks;
 
+constexpr bool completed = true;
+
 struct TaskData : std::enable_shared_from_this<TaskData>
 {
   private:
@@ -120,13 +122,9 @@
             [self = shared_from_this()](sdbusplus::message::message &message) {
                 boost::system::error_code ec;
 
-                // set to complete before callback incase user wants a different
-                // status
-                self->state = "Completed";
-
                 // callback to return True if callback is done, callback needs
                 // to update status itself if needed
-                if (self->callback(ec, message, self))
+                if (self->callback(ec, message, self) == task::completed)
                 {
                     self->timer.cancel();
                     self->finishTask();
@@ -136,10 +134,6 @@
                         [self] { self->match.reset(); });
                     return;
                 }
-
-                // set back to running if callback returns false to keep
-                // callback alive
-                self->state = "Running";
             });
         timer.expires_after(timeout);
         timer.async_wait(
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
index a47aca2..3ca7721 100644
--- a/redfish-core/lib/update_service.hpp
+++ b/redfish-core/lib/update_service.hpp
@@ -117,7 +117,77 @@
                     activateImage(objPath.str, objInfo[0].first);
                     if (asyncResp)
                     {
-                        redfish::messages::success(asyncResp->res);
+                        std::shared_ptr<task::TaskData> task =
+                            task::TaskData::createTask(
+                                [](boost::system::error_code ec,
+                                   sdbusplus::message::message &msg,
+                                   const std::shared_ptr<task::TaskData>
+                                       &taskData) {
+                                    if (ec)
+                                    {
+                                        return task::completed;
+                                    }
+
+                                    std::string iface;
+                                    boost::container::flat_map<
+                                        std::string, std::variant<std::string>>
+                                        values;
+                                    msg.read(iface, values);
+                                    auto findActivation =
+                                        values.find("Activation");
+                                    if (findActivation == values.end())
+                                    {
+                                        return !task::completed;
+                                    }
+                                    std::string *state =
+                                        std::get_if<std::string>(
+                                            &(findActivation->second));
+
+                                    if (state == nullptr)
+                                    {
+                                        taskData->messages.emplace_back(
+                                            messages::internalError());
+                                        return task::completed;
+                                    }
+
+                                    if (boost::ends_with(*state, "Invalid") ||
+                                        boost::ends_with(*state, "Failed"))
+                                    {
+                                        taskData->state = "Exception";
+                                        taskData->status = "Warning";
+                                        taskData->messages.emplace_back(
+                                            messages::invalidObject(
+                                                "/redfish/v1/UpdateService/"));
+                                        return task::completed;
+                                    }
+
+                                    if (boost::ends_with(*state, "Staged"))
+                                    {
+                                        taskData->state = "Pending";
+                                        return !task::completed;
+                                    }
+
+                                    if (boost::ends_with(*state, "Active"))
+                                    {
+                                        taskData->messages.emplace_back(
+                                            messages::success());
+                                        taskData->state = "Completed";
+                                        return task::completed;
+                                    }
+
+                                    // 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',arg0='xyz.openbmc_"
+                                "project.Software.Activation',path='" +
+                                    objPath.str + "'");
+                        task->startTimer(std::chrono::minutes(5));
+                        task->populateResp(asyncResp->res);
                     }
                     fwUpdateInProgress = false;
                 },