DeleteFruVpd:Conditional FRU deletion

This commit adds a check in deleteFruVpd API to prevent deletion of FRUs
which are present and whose presence is handled by external service.

```
Test:
- On Everest system, see fan0 VPD is present on PIM
- Set "Present" property of fan0 to false using busctl
- See fan0 VPD is cleared from PIM
- Set "Present" property of fan0 to true using busctl
- Execute DeleteFruVpd API from vpd-manager D-Bus interface
- DeleteFruVpd fails
- Check VPD of pcie_card2 using vpd-tool and see it is present
- Execute deleteFruVpd on pcie_card2 and see it is successful
```

Change-Id: I69e3f805e3170d86befd95b2efc1a59069d762d6
Signed-off-by: Souvik Roy <souvikroyofficial10@gmail.com>
diff --git a/vpd-manager/include/utility/json_utility.hpp b/vpd-manager/include/utility/json_utility.hpp
index 4bf3846..dad346e 100644
--- a/vpd-manager/include/utility/json_utility.hpp
+++ b/vpd-manager/include/utility/json_utility.hpp
@@ -1198,5 +1198,51 @@
     }
     return l_frusWithPresenceMonitoring;
 }
+
+/**
+ * @brief API which tells if the FRU's presence is handled
+ *
+ * For a given FRU, this API checks if it's presence is handled by vpd-manager
+ * by checking the "handlePresence" tag.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ * @param[in] i_vpdFruPath - EEPROM path.
+ *
+ * @return true if FRU presence is handled, false otherwise.
+ */
+inline bool isFruPresenceHandled(const nlohmann::json& i_sysCfgJsonObj,
+                                 const std::string& i_vpdFruPath)
+{
+    try
+    {
+        if (i_vpdFruPath.empty())
+        {
+            throw std::runtime_error("Given FRU path is empty.");
+        }
+
+        if (!i_sysCfgJsonObj.contains("frus"))
+        {
+            throw JsonException("Invalid system config JSON object.");
+        }
+
+        if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
+        {
+            logging::logMessage(
+                "JSON object does not contain EEPROM path " + i_vpdFruPath);
+            return false;
+        }
+
+        return i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0).value(
+            "handlePresence", true);
+    }
+    catch (const std::exception& l_ex)
+    {
+        logging::logMessage(
+            "Failed to check if FRU's presence is handled, reason:" +
+            std::string(l_ex.what()));
+    }
+
+    return false;
+}
 } // namespace jsonUtility
 } // namespace vpd
diff --git a/vpd-manager/src/worker.cpp b/vpd-manager/src/worker.cpp
index 48d0c3b..b8b5d2c 100644
--- a/vpd-manager/src/worker.cpp
+++ b/vpd-manager/src/worker.cpp
@@ -1609,10 +1609,19 @@
 
         if (auto l_value = std::get_if<bool>(&l_presentPropValue))
         {
-            if (!(*l_value))
+            // check if FRU's Present property is handled by vpd-manager
+            const auto& l_isFruPresenceHandled =
+                jsonUtility::isFruPresenceHandled(m_parsedJson, l_fruPath);
+
+            if (!(*l_value) && l_isFruPresenceHandled)
             {
                 throw std::runtime_error("Given FRU is not present");
             }
+            else if (*l_value && !l_isFruPresenceHandled)
+            {
+                throw std::runtime_error(
+                    "Given FRU is present and its presence is not handled by vpd-manager.");
+            }
             else
             {
                 if (jsonUtility::isActionRequired(m_parsedJson, l_fruPath,