Log insertion/removal of all Hard Disk Drives

Insertion and removal events were only being logged for NVMe
drives. The D-Bus event system could only be enabled for NVMe
drives. The D-Bus method allowed the NVMe serial number to be added to
the insertion/removal event. SAS/SATA insertion/removal was not
detected. The only time SAS/SATA drives were detected was during HSPB
power on.

The changes here log the insertion and removal of all drives.

Tested:
Created an in code temporary test that toggled the Drive 1 Present bit
during every UpdateDrives call. This was done because physically
inserting/removing the drive is impractical.
Confirmed after each toggle there was a journal event for "Iventory
Added" and "Inventory Removed", and that the extended data included
the drive number.

Change-Id: I48ce1e0dc15cf8a42a498bf8dbe93a88ebd30a58
Signed-off-by: Johnathan Mantey <johnathanx.mantey@intel.com>
diff --git a/hsbp-manager/src/hsbp_manager.cpp b/hsbp-manager/src/hsbp_manager.cpp
index 85de91e..57d3477 100644
--- a/hsbp-manager/src/hsbp_manager.cpp
+++ b/hsbp-manager/src/hsbp_manager.cpp
@@ -229,10 +229,10 @@
             if (key == "SerialNumber")
             {
                 serialNumber = value;
+                serialNumberInitialized = true;
             }
         }
         assetIface->initialize();
-        logPresent();
     }
 
     void markFailed(void)
@@ -268,21 +268,30 @@
         }
         itemIface->set_property("Present", set);
         isPresent = set;
-        if (!isPresent)
-        {
-            logDeviceRemoved("Drive", std::to_string(index), serialNumber);
-            loggedPresent = false;
-        }
     }
 
     void logPresent()
     {
-        if (!isPresent || loggedPresent)
+        if (isNvme && !serialNumberInitialized)
         {
+            // wait until NVMe asset is updated to include the serial number
+            // from the NVMe drive
             return;
         }
-        logDeviceAdded("Drive", std::to_string(index), serialNumber);
-        loggedPresent = true;
+
+        if (!isPresent && loggedPresent)
+        {
+            loggedPresent = false;
+            logDeviceRemoved("Drive", std::to_string(index), serialNumber);
+            serialNumber = "N/A";
+            serialNumberInitialized = false;
+            return;
+        }
+        else if (isPresent && !loggedPresent)
+        {
+            loggedPresent = true;
+            logDeviceAdded("Drive", std::to_string(index), serialNumber);
+        }
     }
 
     std::shared_ptr<sdbusplus::asio::dbus_interface> itemIface;
@@ -296,6 +305,7 @@
     bool isPresent;
     size_t index;
     std::string serialNumber = "N/A";
+    bool serialNumberInitialized = false;
     bool loggedPresent = false;
 };
 
@@ -457,13 +467,13 @@
 
     void createDrives()
     {
-        uint8_t nvme = ifdet ^ presence;
         for (size_t ii = 0; ii < maxDrives; ii++)
         {
-            bool isNvme = nvme & (1 << ii);
-            bool isPresent = isNvme || (presence & (1 << ii));
-            bool isFailed = !isPresent || failed & (1 << ii);
-            bool isRebuilding = !isPresent && (rebuilding & (1 << ii));
+            uint8_t driveSlot = (1 << ii);
+            bool isNvme = ((ifdet & driveSlot) && !(presence & driveSlot));
+            bool isPresent = isNvme || (presence & driveSlot);
+            bool isFailed = !isPresent || failed & driveSlot;
+            bool isRebuilding = !isPresent && (rebuilding & driveSlot);
 
             // +1 to convert from 0 based to 1 based
             size_t driveIndex = (backplaneIndex * maxDrives) + ii + 1;
@@ -477,20 +487,19 @@
 
     void updateDrives()
     {
-
-        uint8_t nvme = ifdet ^ presence;
         size_t ii = 0;
 
         for (auto it = drives.begin(); it != drives.end(); it++, ii++)
         {
-            bool isNvme = nvme & (1 << ii);
-            bool isPresent = isNvme || (presence & (1 << ii));
-            bool isFailed = !isPresent || (failed & (1 << ii));
-            bool isRebuilding = isPresent && (rebuilding & (1 << ii));
+            uint8_t driveSlot = (1 << ii);
+            bool isNvme = ((ifdet & driveSlot) && !(presence & driveSlot));
+            bool isPresent = isNvme || (presence & driveSlot);
+            bool isFailed = !isPresent || (failed & driveSlot);
+            bool isRebuilding = isPresent && (rebuilding & driveSlot);
 
             it->isNvme = isNvme;
-
             it->setPresent(isPresent);
+            it->logPresent();
 
             it->rebuildingIface->set_property("Rebuilding", isRebuilding);
             if (isFailed || isRebuilding)
@@ -628,14 +637,6 @@
         return true;
     }
 
-    void logDrivePresence()
-    {
-        for (auto& drive : drives)
-        {
-            drive.logPresent();
-        }
-    }
-
     virtual ~Backplane()
     {
         objServer.remove_interface(hsbpItemIface);
@@ -727,19 +728,11 @@
                     continue;
                 }
 
-                auto callback = std::make_shared<std::function<void()>>([]() {
-                    for (auto [_, backplane] : backplanes)
-                    {
-                        backplane->logDrivePresence();
-                    }
-                });
-
                 conn->async_method_call(
-                    [callback, path](
-                        const boost::system::error_code ec2,
-                        const boost::container::flat_map<
-                            std::string, std::variant<uint64_t, std::string>>&
-                            values) {
+                    [path](const boost::system::error_code ec2,
+                           const boost::container::flat_map<
+                               std::string,
+                               std::variant<uint64_t, std::string>>& values) {
                         if (ec2)
                         {
                             std::cerr << "Error Getting Config "
@@ -869,10 +862,6 @@
                         std::advance(it, driveIndex);
 
                         it->createAsset(assetInventory);
-                        if (callback.use_count() == 1)
-                        {
-                            (*callback)();
-                        }
                     },
                     owner, path, "org.freedesktop.DBus.Properties", "GetAll",
                     "" /*all interface items*/);