host-gpio-monitor: Use systemd template

The systemd target gbmc-bare-metal-active.target is being changed to a
template, in order to support multi-host systems. The commit updates the
host-gpio-monitor functionality accordingly. The host number now gets
passed in as an argument.

Tested:
Set the bare metal flag /var/google/config-package/enable-bm.flag on the
BMC. Started host-gpio-monitor@0.service, which then started
gbmc-bare-metal-active@0.target. Then rebooted the host, at which point,
the host-gpio-monitor@0.service disabled
gbmc-bare-metal-active@0.target.

Change-Id: I02a0b11996aa2ee168e682fbf61f3f1a8cf01771
Signed-off-by: John Wedig <johnwedig@google.com>
diff --git a/subprojects/bare-metal-host-monitor/host_gpio_monitor.cpp b/subprojects/bare-metal-host-monitor/host_gpio_monitor.cpp
index 0c9f697..5deea2a 100644
--- a/subprojects/bare-metal-host-monitor/host_gpio_monitor.cpp
+++ b/subprojects/bare-metal-host-monitor/host_gpio_monitor.cpp
@@ -1,4 +1,7 @@
 
+#include "absl/flags/flag.h"
+#include "absl/flags/parse.h"
+
 #include <boost/asio/io_context.hpp>
 #include <boost/asio/steady_timer.hpp>
 #include <phosphor-logging/lg2.hpp>
@@ -7,8 +10,13 @@
 #include <sdbusplus/bus.hpp>
 #include <sdbusplus/bus/match.hpp>
 
+#include <format>
+
+ABSL_FLAG(std::string, host_label, "0",
+          "Label for the host in question. Usually this is an integer.");
+
 const constexpr char* OperatingSystemService =
-    "xyz.openbmc_project.State.OperatingSystem";
+    "xyz.openbmc_project.State.OperatingSystem{}";
 const constexpr char* OperatingSystemPath = "/xyz/openbmc_project/state/os";
 const constexpr char* OperatingSystemStatusInterface =
     "xyz.openbmc_project.State.OperatingSystem.Status";
@@ -17,29 +25,34 @@
     "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus.Standby";
 const constexpr char* OperatingSystemStateInactive =
     "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus.Inactive";
-const constexpr char* BareMetalActiveTarget = "gbmc-bare-metal-active.target";
+const constexpr char* BareMetalActiveTargetTemplate =
+    "gbmc-bare-metal-active@{}.target";
 
 const constexpr char* SystemdService = "org.freedesktop.systemd1";
 const constexpr char* SystemdManagerObject = "/org/freedesktop/systemd1";
 const constexpr char* SystemdManagerInterface =
     "org.freedesktop.systemd1.Manager";
 
-void setUnitStatus(sdbusplus::asio::connection& bus, bool status)
+void setUnitStatus(sdbusplus::asio::connection& bus, bool status,
+                   const std::string& host_instance)
 {
     auto method = bus.new_method_call(SystemdService, SystemdManagerObject,
                                       SystemdManagerInterface,
                                       status ? "StartUnit" : "StopUnit");
-    method.append(BareMetalActiveTarget, "replace");
+    method.append(std::format(BareMetalActiveTargetTemplate, host_instance),
+                  "replace");
 
     bus.call(method);
 }
 
 void checkPostComplete(sdbusplus::asio::connection& bus,
-                       const std::string& state, bool action)
+                       const std::string& state, bool action,
+                       const std::string& host_instance)
 {
     sdbusplus::asio::getProperty<std::string>(
-        bus, OperatingSystemService, OperatingSystemPath,
-        OperatingSystemStatusInterface, OperatingSystemStateProperty,
+        bus, std::format(OperatingSystemService, host_instance),
+        OperatingSystemPath, OperatingSystemStatusInterface,
+        OperatingSystemStateProperty,
         [&, state, action](const boost::system::error_code& ec,
                            const std::string& postCompleteState) {
             if (ec)
@@ -58,25 +71,30 @@
              */
             if (postCompleteState == state)
             {
-                setUnitStatus(bus, action);
+                setUnitStatus(bus, action, host_instance);
             }
         });
 }
 
 /* This only gets called once on startup. */
-void checkPostCompleteStartup(sdbusplus::asio::connection& bus)
+void checkPostCompleteStartup(sdbusplus::asio::connection& bus,
+                              const std::string& host_instance)
 {
-    checkPostComplete(bus, OperatingSystemStateStandby, true);
+    checkPostComplete(bus, OperatingSystemStateStandby, true, host_instance);
 }
 
 /* Gets called when a GPIO state change is detected. */
-void checkPostCompleteEvent(sdbusplus::asio::connection& bus)
+void checkPostCompleteEvent(sdbusplus::asio::connection& bus,
+                            const std::string& host_instance)
 {
-    checkPostComplete(bus, OperatingSystemStateInactive, false);
+    checkPostComplete(bus, OperatingSystemStateInactive, false, host_instance);
 }
 
-int main()
+int main(int argc, char** argv)
 {
+    absl::ParseCommandLine(argc, argv);
+    std::string host_label = absl::GetFlag(FLAGS_host_label);
+
     try
     {
         /* Setup connection to dbus. */
@@ -84,7 +102,7 @@
         auto conn = sdbusplus::asio::connection(io);
 
         /* check IPMI status at startup */
-        checkPostCompleteStartup(conn);
+        checkPostCompleteStartup(conn, host_label);
         /*
          * Set up an event handler to process Post Complete GPIO state changes.
          */
@@ -128,7 +146,7 @@
                          * Stop the bare metal active target if the post
                          * complete got deasserted.
                          */
-                        checkPostCompleteEvent(conn);
+                        checkPostCompleteEvent(conn, host_label);
                     });
             });