Call systemd target on timer expiration

User can pass an optional command line argument stating which
systemd target needs to be called on timer expiration. The timeout
handler will make sure that the systemd target is started prior to
exiting.

Change-Id: I37213ab28ad4166a47920dcb3dc79769c7f2af1a
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
diff --git a/mainapp.cpp b/mainapp.cpp
index b9e6121..7751aa9 100644
--- a/mainapp.cpp
+++ b/mainapp.cpp
@@ -72,7 +72,8 @@
     bus.attach_event(eventP.get(), SD_EVENT_PRIORITY_NORMAL);
 
     // Create a watchdog object
-    phosphor::watchdog::Watchdog watchdog(bus, path.c_str(), eventP);
+    phosphor::watchdog::Watchdog watchdog(bus, path.c_str(),
+                                          eventP, std::move(target));
 
     // Claim the bus
     bus.request_name(service.c_str());
diff --git a/watchdog.cpp b/watchdog.cpp
index e5e8aff..99ef679 100644
--- a/watchdog.cpp
+++ b/watchdog.cpp
@@ -9,6 +9,11 @@
 using namespace std::chrono_literals;
 using namespace phosphor::logging;
 
+// systemd service to kick start a target.
+constexpr auto SYSTEMD_SERVICE    = "org.freedesktop.systemd1";
+constexpr auto SYSTEMD_ROOT       = "/org/freedesktop/systemd1";
+constexpr auto SYSTEMD_INTERFACE  = "org.freedesktop.systemd1.Manager";
+
 // Enable or disable watchdog
 bool Watchdog::enabled(bool value)
 {
@@ -94,9 +99,18 @@
 // Optional callback function on timer expiration
 void Watchdog::timeOutHandler()
 {
-    log<level::INFO>("Optional callback called");
-    // TODO: Need to call the user passed systemd
-    // target on this condition
+    if (!target.empty())
+    {
+        auto method = bus.new_method_call(SYSTEMD_SERVICE,
+                                          SYSTEMD_ROOT,
+                                          SYSTEMD_INTERFACE,
+                                          "StartUnit");
+        method.append(target);
+        method.append("replace");
+
+        bus.call_noreply(method);
+    }
+    return;
 }
 
 } // namespace watchdog
diff --git a/watchdog.hpp b/watchdog.hpp
index 1a7a410..79df438 100644
--- a/watchdog.hpp
+++ b/watchdog.hpp
@@ -29,15 +29,18 @@
 
         /** @brief Constructs the Watchdog object
          *
-         *  @param[in] bus     - DBus bus to attach to
-         *  @param[in] objPath - Object path to attach to
+         *  @param[in] bus     - DBus bus to attach to.
+         *  @param[in] objPath - Object path to attach to.
          *  @param[in] event   - reference to sd_event unique pointer
+         *  @param[in] target  - systemd target to be called into on timeout
          */
         Watchdog(sdbusplus::bus::bus& bus,
                 const char* objPath,
-                EventPtr& event) :
+                EventPtr& event,
+                std::string&& target = std::string()) :
             WatchdogInherits(bus, objPath),
             bus(bus),
+            target(std::move(target)),
             timer(event, std::bind(&Watchdog::timeOutHandler, this))
         {
             // Nothing
@@ -83,6 +86,9 @@
         /** @brief sdbusplus handle */
         sdbusplus::bus::bus& bus;
 
+        /** @brief Systemd unit to be started when the timer expires */
+        std::string target;
+
         /** @brief Contained timer object */
         Timer timer;