Add retries when getting dbus properties

We have found that the dbus requests to Entity Manager sometimes time
out at startup, when getting the dbus properties from the Entity Manager
config object. This commit adds retries, similar to how dbus-sensors
will retry these requests, if needed.

Tested:
Observed the dbus request to Entity Manager get retried on a machine,
and then it succeeded on the second attempt.

Signed-off-by: John Wedig <johnwedig@google.com>
Change-Id: I924703e9be0879489477cc31644ef280429c347b
diff --git a/include/getConfig.hpp b/include/getConfig.hpp
index c833a39..077cdb6 100644
--- a/include/getConfig.hpp
+++ b/include/getConfig.hpp
@@ -60,8 +60,10 @@
      *
      *  @param[in] path - D-Bus object path of the config object.
      *  @param[in] owner - D-Bus service that owns the config object.
+     *  @param[in] retries - (optional) Number of times to retry, if needed.
      */
-    void getStorageInfo(const std::string& path, const std::string& owner);
+    void getStorageInfo(const std::string& path, const std::string& owner,
+                        size_t retries = 5);
 
     /** @brief Map containing config objects with corresponding properties. */
     ManagedStorageType respData;
diff --git a/src/getConfig.cpp b/src/getConfig.cpp
index f752b77..563a057 100644
--- a/src/getConfig.cpp
+++ b/src/getConfig.cpp
@@ -1,9 +1,11 @@
 
 #include "getConfig.hpp"
 
+#include <boost/asio/steady_timer.hpp>
 #include <phosphor-logging/lg2.hpp>
 #include <sdbusplus/asio/connection.hpp>
 
+#include <chrono>
 #include <cstdlib>
 #include <memory>
 #include <string>
@@ -27,18 +29,38 @@
               std::vector<std::pair<std::string, std::vector<std::string>>>>>;
 
 void GetStorageConfiguration::getStorageInfo(const std::string& path,
-                                             const std::string& owner)
+                                             const std::string& owner,
+                                             size_t retries)
 {
     std::shared_ptr<GetStorageConfiguration> self = shared_from_this();
     self->dbusConnection->async_method_call(
-        [self, path, owner](
+        [self, path, owner, retries](
             const boost::system::error_code ec,
             boost::container::flat_map<std::string, BasicVariantType>& data) {
         if (ec)
         {
-            lg2::error("Error getting properties for {PATH}", "PATH", path,
-                       "REDFISH_MESSAGE_ID",
-                       std::string("OpenBMC.0.1.GetStorageInfoFail"));
+            lg2::error(
+                "Error getting properties for {PATH}: {RETRIES} retries left",
+                "PATH", path, "RETRIES", retries - 1, "REDFISH_MESSAGE_ID",
+                std::string("OpenBMC.0.1.GetStorageInfoFail"));
+            if (retries == 0U)
+            {
+                return;
+            }
+
+            auto timer = std::make_shared<boost::asio::steady_timer>(
+                self->dbusConnection->get_io_context());
+            timer->expires_after(std::chrono::seconds(10));
+            timer->async_wait([self, timer, path, owner,
+                               retries](boost::system::error_code ec) {
+                if (ec)
+                {
+                    lg2::error("Timer error!");
+                    return;
+                }
+                self->getStorageInfo(path, owner, retries - 1);
+            });
+
             return;
         }