Reset lamps after reboot

In case lamp test has been triggered and reboot takes place,
even after reboot the lamps are found to be in the on state.

The commit switches off the lamps in case such situation is
found and restores the LEDs to the state in which they were
before lamp test was triggered.

Change-Id: I3d199b7066751e89bd6faffc38af3e36877ca003
Signed-off-by: Sunny Srivastava <sunnsr25@in.ibm.com>
diff --git a/manager/lamptest/lamptest.cpp b/manager/lamptest/lamptest.cpp
index 3dfaaa5..b306e51 100644
--- a/manager/lamptest/lamptest.cpp
+++ b/manager/lamptest/lamptest.cpp
@@ -10,6 +10,8 @@
 {
 
 using Json = nlohmann::json;
+static const fs::path lampTestIndicator =
+    "/var/lib/phosphor-led-manager/lamp-test-running";
 
 bool LampTest::processLEDUpdates(const ActionSet& ledsAssert,
                                  const ActionSet& ledsDeAssert)
@@ -82,6 +84,15 @@
         manager.drivePhysicalLED(path, Layout::Action::Off, 0, 0);
     }
 
+    if (std::filesystem::exists(lampTestIndicator))
+    {
+        if (!std::filesystem::remove(lampTestIndicator))
+        {
+            lg2::error(
+                "Error removing lamp test on indicator file after lamp test execution.");
+        }
+    }
+
     isLampTestRunning = false;
     restorePhysicalLedStates();
 }
@@ -197,6 +208,19 @@
     // Notify host to start the lamp test
     doHostLampTest(true);
 
+    // Create a file to maintain the state across reboots that Lamp test is on.
+    // This is required as there was a scenario where it has been found that
+    // LEDs remains in "on" state if lamp test is triggered and reboot takes
+    // place.
+    const auto ledDirectory = lampTestIndicator.parent_path();
+
+    if (!fs::exists(ledDirectory))
+    {
+        fs::create_directories(ledDirectory);
+    }
+
+    std::ofstream(lampTestIndicator.c_str());
+
     // Set all the Physical action to On for lamp test
     for (const auto& path : physicalLEDPaths)
     {
@@ -328,5 +352,29 @@
     }
     return;
 }
+
+void LampTest::clearLamps()
+{
+    if (std::filesystem::exists(lampTestIndicator))
+    {
+        // we need to off all the LEDs.
+        phosphor::led::utils::DBusHandler dBusHandler;
+        std::vector<std::string> physicalLedPaths = dBusHandler.getSubTreePaths(
+            phosphor::led::phyLedPath, phosphor::led::phyLedIntf);
+
+        for (const auto& path : physicalLedPaths)
+        {
+            manager.drivePhysicalLED(path, phosphor::led::Layout::Action::Off,
+                                     0, 0);
+        }
+
+        // Also remove the lamp test on indicator file.
+        if (!std::filesystem::remove(lampTestIndicator))
+        {
+            lg2::error(
+                "Error removing lamp test on indicator file after lamp test execution.");
+        }
+    }
+}
 } // namespace led
 } // namespace phosphor
diff --git a/manager/lamptest/lamptest.hpp b/manager/lamptest/lamptest.hpp
index 0de9082..f4fb5c5 100644
--- a/manager/lamptest/lamptest.hpp
+++ b/manager/lamptest/lamptest.hpp
@@ -73,6 +73,14 @@
     bool processLEDUpdates(const ActionSet& ledsAssert,
                            const ActionSet& ledsDeAssert);
 
+    /** @brief Clear LEDs triggerred by lamptest
+     * When system reboots during lamptest, leds triggerred by lamptest needs to
+     * be cleared in the upcoming boot. This method clears all the leds along
+     * with the persisted lamp test indicator file so that there is no sign of
+     * lamptest.
+     */
+    void clearLamps();
+
   private:
     /** @brief Timer used for LEDs lamp test period */
     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer;