Activation: Start service files and wait for completion

In this commit, the BMC activation flow is implemented. When the user
starts an activation, two service files are called to create read-only
and read-write volumes. Once these service files are finished running,
activation is marked as complete.

Resolves openbmc/openbmc#1756

Change-Id: I3874c2d04a1a2b07eea4e34789ba5ece0ff6979c
Signed-off-by: Michael Tritz <mtritz@us.ibm.com>
diff --git a/activation.cpp b/activation.cpp
index 9f9a16e..1e04230 100644
--- a/activation.cpp
+++ b/activation.cpp
@@ -10,6 +10,22 @@
 
 namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
 
+constexpr auto SYSTEMD_SERVICE   = "org.freedesktop.systemd1";
+constexpr auto SYSTEMD_PATH      = "/org/freedesktop/systemd1";
+constexpr auto SIGNAL_INTERFACE  = "/org/freedesktop/systemd1";
+constexpr auto MANAGER_INTERFACE = "org.freedesktop.systemd1.Manager";
+
+void Activation::subscribeToSystemdSignals()
+{
+    auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
+                                            SYSTEMD_PATH,
+                                            SIGNAL_INTERFACE,
+                                            "Subscribe");
+    this->bus.call_noreply(method);
+
+    return;
+}
+
 auto Activation::activation(Activations value) ->
         Activations
 {
@@ -21,28 +37,50 @@
 
     if (value == softwareServer::Activation::Activations::Activating)
     {
-        if (!activationBlocksTransition)
+        if (rwVolumeCreated == false && roVolumeCreated == false)
         {
-            activationBlocksTransition =
-                      std::make_unique<ActivationBlocksTransition>(
-                                bus,
-                                path);
-        }
+            if (!activationBlocksTransition)
+            {
+                activationBlocksTransition =
+                          std::make_unique<ActivationBlocksTransition>(
+                                    bus,
+                                    path);
+            }
 
-        //TODO openbmc/openbmc#1756 - Add Logic for Code Update
-        if (!redundancyPriority)
+            auto method = bus.new_method_call(
+                    SYSTEMD_SERVICE,
+                    SYSTEMD_PATH,
+                    MANAGER_INTERFACE,
+                    "StartUnit");
+            method.append("obmc-flash-bmc-ubirw.service", "replace");
+            bus.call_noreply(method);
+
+            auto roServiceFile = "obmc-flash-bmc-ubiro@" + versionId +
+                    ".service";
+            method = bus.new_method_call(
+                    SYSTEMD_SERVICE,
+                    SYSTEMD_PATH,
+                    MANAGER_INTERFACE,
+                    "StartUnit");
+            method.append(roServiceFile, "replace");
+            bus.call_noreply(method);
+        }
+        else if (rwVolumeCreated == true && roVolumeCreated == true)
         {
-            redundancyPriority =
-                      std::make_unique<RedundancyPriority>(
-                                bus,
-                                path,
-                                *this,
-                                0);
-        }
+            if (!redundancyPriority)
+            {
+                redundancyPriority =
+                          std::make_unique<RedundancyPriority>(
+                                    bus,
+                                    path,
+                                    *this,
+                                    0);
+            }
 
-        activationBlocksTransition.reset(nullptr);
-        return softwareServer::Activation::activation(
-                softwareServer::Activation::Activations::Active);
+            activationBlocksTransition.reset(nullptr);
+            return softwareServer::Activation::activation(
+                    softwareServer::Activation::Activations::Active);
+        }
     }
     else
     {
@@ -54,6 +92,9 @@
 auto Activation::requestedActivation(RequestedActivations value) ->
         RequestedActivations
 {
+    rwVolumeCreated = false;
+    roVolumeCreated = false;
+
     if ((value == softwareServer::Activation::RequestedActivations::Active) &&
         (softwareServer::Activation::requestedActivation() !=
                   softwareServer::Activation::RequestedActivations::Active))
@@ -77,6 +118,45 @@
     return softwareServer::RedundancyPriority::priority(value);
 }
 
+void Activation::unitStateChange(sdbusplus::message::message& msg)
+{
+    uint32_t newStateID {};
+    sdbusplus::message::object_path newStateObjPath;
+    std::string newStateUnit{};
+    std::string newStateResult{};
+
+    //Read the msg and populate each variable
+    msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
+
+    auto rwServiceFile = "obmc-flash-bmc-ubirw.service";
+    auto roServiceFile = "obmc-flash-bmc-ubiro@" + versionId + ".service";
+
+    if(newStateUnit == rwServiceFile && newStateResult == "done")
+    {
+        rwVolumeCreated = true;
+    }
+
+    if(newStateUnit == roServiceFile && newStateResult == "done")
+    {
+        roVolumeCreated = true;
+    }
+
+    if(rwVolumeCreated && roVolumeCreated)
+    {
+        Activation::activation(
+                softwareServer::Activation::Activations::Activating);
+    }
+
+    if((newStateUnit == rwServiceFile || newStateUnit == roServiceFile) &&
+        (newStateResult == "failed" || newStateResult == "dependency"))
+    {
+        Activation::activation(softwareServer::Activation::Activations::Failed);
+    }
+
+    return;
+}
+
+
 } // namespace updater
 } // namespace software
 } // namespace phosphor