VPD Tool : Force Collect On Hardware

This commit adds an additional option called --forceReset
in the vpd-tool.

This option is used to restart the Inventory Manager service
and retrigger the udev events which launches the VPD services.

How to use the option?
./vpd-tool --forceReset/-f/-F

This option does not take any arguments.

Tested on simics.

Signed-off-by: PriyangaRamasamy <priyanga24@in.ibm.com>
Change-Id: Icd1ad30389432f731f21cc84999f7a54fcbbec65
diff --git a/meson.build b/meson.build
index b61f44a..2f0ec24 100644
--- a/meson.build
+++ b/meson.build
@@ -30,7 +30,8 @@
                        'IFACE' : '"' + get_option('IFACE') + '"',
 		       'OBJECT_MAPPER_SERVICE' : '"'+get_option('OBJECT_MAPPER_SERVICE')+'"',
 		       'OBJECT_MAPPER_OBJECT' : '"'+get_option('OBJECT_MAPPER_OBJECT')+'"',
-		       'POWER_SUPPLY_TYPE_INTERFACE' : '"'+get_option('POWER_SUPPLY_TYPE_INTERFACE')+'"'
+		       'POWER_SUPPLY_TYPE_INTERFACE' : '"'+get_option('POWER_SUPPLY_TYPE_INTERFACE')+'"',
+		       'INVENTORY_MANAGER_CACHE' : '"'+get_option('INVENTORY_MANAGER_CACHE')+'"'
                        }
   )
         ibm_read_vpd_SOURCES = ['ibm_vpd_app.cpp',
diff --git a/meson_options.txt b/meson_options.txt
index df9b3ac..50ce922 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -14,3 +14,4 @@
 option('OBJECT_MAPPER_SERVICE', type : 'string', value : 'xyz.openbmc_project.ObjectMapper', description : 'Object Mapper service')
 option('OBJECT_MAPPER_OBJECT', type : 'string', value : '/xyz/openbmc_project/object_mapper', description : 'One of the objects in Object Mapper service')
 option('POWER_SUPPLY_TYPE_INTERFACE', type : 'string', value : 'xyz.openbmc_project.Inventory.Item.PowerSupply', description : 'Power Supply Type Interface')
+option('INVENTORY_MANAGER_CACHE', type : 'string', value : '/var/lib/phosphor-inventory-manager', description : 'Path to inventory manager cache')
diff --git a/vpd_tool.cpp b/vpd_tool.cpp
index 0514cc5..9129eca 100644
--- a/vpd_tool.cpp
+++ b/vpd_tool.cpp
@@ -60,6 +60,10 @@
             ->needs(kw)
             ->needs(valOption);
 
+    auto forceResetFlag = app.add_flag(
+        "--forceReset, -f, -F", "Force Collect for Hardware. { vpd-tool-exe "
+                                "--forceReset/-f/-F }");
+
     CLI11_PARSE(app, argc, argv);
 
     ifstream inventoryJson(INVENTORY_JSON);
@@ -93,6 +97,12 @@
             rc = vpdToolObj.updateKeyword();
         }
 
+        else if (*forceResetFlag)
+        {
+            VpdTool vpdToolObj;
+            vpdToolObj.forceReset(jsObject);
+        }
+
         else
         {
             throw runtime_error("One of the valid options is required. Refer "
diff --git a/vpd_tool_impl.cpp b/vpd_tool_impl.cpp
index a424312..37fede1 100644
--- a/vpd_tool_impl.cpp
+++ b/vpd_tool_impl.cpp
@@ -30,7 +30,7 @@
         "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths");
     properties.append(INVENTORY_PATH);
     properties.append(0);
-    properties.append(std::array<const char*, 1>{POWER_SUPPLY_TYPE_INTERFACE});
+    properties.append(array<const char*, 1>{POWER_SUPPLY_TYPE_INTERFACE});
 
     auto result = bus.call(properties);
 
@@ -415,3 +415,45 @@
     }
     return 0;
 }
+
+void VpdTool::forceReset(const nlohmann::basic_json<>& jsObject)
+{
+    for (const auto& itemFRUS : jsObject["frus"].items())
+    {
+        for (const auto& itemEEPROM : itemFRUS.value().items())
+        {
+            string fru = itemEEPROM.value().at("inventoryPath");
+
+            fs::path fruCachePath = INVENTORY_MANAGER_CACHE;
+            fruCachePath += INVENTORY_PATH;
+            fruCachePath += fru;
+
+            try
+            {
+                for (const auto& it : fs::directory_iterator(fruCachePath))
+                {
+                    if (fs::is_regular_file(it.status()))
+                    {
+                        fs::remove(it);
+                    }
+                }
+            }
+            catch (const fs::filesystem_error& e)
+            {
+            }
+        }
+    }
+
+    string udevRemove = "udevadm trigger -c remove -s \"*nvmem*\" -v";
+    system(udevRemove.c_str());
+
+    string invManagerRestart =
+        "systemctl restart xyz.openbmc_project.Inventory.Manager.service";
+    system(invManagerRestart.c_str());
+
+    string sysVpdStop = "systemctl stop system-vpd.service";
+    system(sysVpdStop.c_str());
+
+    string udevAdd = "udevadm trigger -c add -s \"*nvmem*\" -v";
+    system(udevAdd.c_str());
+}
diff --git a/vpd_tool_impl.hpp b/vpd_tool_impl.hpp
index 1ac96bd..6aec28c 100644
--- a/vpd_tool_impl.hpp
+++ b/vpd_tool_impl.hpp
@@ -109,7 +109,7 @@
      * Get the power supply fru paths from Object mapper service.
      *
      * @param[out] powSuppFrus - Reference to a vector which has the power
-     * supply fru paths.
+     * supply fruPaths.
      */
     void getPowerSupplyFruPath(std::vector<std::string>& powSuppFrus);
 
@@ -155,9 +155,20 @@
     int updateKeyword();
 
     /**
+     * @brief Force Reset
+     * Clearing the inventory cache data and restarting the
+     * phosphor inventory manager and also retriggering all the
+     * udev events.
+     *
+     * @param[in] jsObject - Inventory JSON specified in configure file.
+     */
+    void forceReset(const nlohmann::basic_json<>& jsObject);
+
+    /**
      * @brief Constructor
      * Constructor is called during the
-     * object instantiation for dumpInventory option.
+     * object instantiation for dumpInventory option and
+     * forceReset option.
      */
     VpdTool()
     {