ItemUpdater: Create dbus object with version id

Use the same version id as the version manager. For that
query the object paths using the mapper and determine if
an item updater object has already been created.

Note: The mapper currently return the BMC version as well
since the interface is the same. To avoid this, a Host-only
interface can be used once those are added, and also
an association once the association work is finalized.

Closes: openbmc/openbmc#1277

Change-Id: I66711ac92a28b7f7ed37006ad6f40de86be1e54c
Signed-off-by: Adriana Kobylak <anoo@us.ibm.com>
diff --git a/item_updater.cpp b/item_updater.cpp
index 9614f50..77dfe1c 100755
--- a/item_updater.cpp
+++ b/item_updater.cpp
@@ -1,3 +1,4 @@
+#include <phosphor-logging/log.hpp>
 #include "config.h"
 #include "item_updater.hpp"
 
@@ -8,17 +9,62 @@
 namespace manager
 {
 
+using namespace phosphor::logging;
+
 int ItemUpdater::createActivation(sd_bus_message* msg,
                                   void* userData,
                                   sd_bus_error* retErr)
 {
-    auto versionId = 1;
     auto* updater = static_cast<ItemUpdater*>(userData);
-    updater->activations.insert(std::make_pair(
-            versionId,
-            std::make_unique<Activation>(
-                    updater->busItem,
-                    SOFTWARE_OBJPATH)));
+    auto mapper = updater->busItem.new_method_call(
+            MAPPER_BUSNAME,
+            MAPPER_PATH,
+            MAPPER_INTERFACE,
+            "GetSubTreePaths");
+    mapper.append(SOFTWARE_OBJPATH,
+                  1, // Depth
+                  std::vector<std::string>({VERSION_IFACE}));
+
+    auto mapperResponseMsg = updater->busItem.call(mapper);
+    if (mapperResponseMsg.is_method_error())
+    {
+        log<level::ERR>("Error in mapper call",
+                        entry("PATH=%s", SOFTWARE_OBJPATH),
+                        entry("INTERFACE=%s", VERSION_IFACE));
+        return -1;
+    }
+
+    std::vector<std::string> mapperResponse;
+    mapperResponseMsg.read(mapperResponse);
+    if (mapperResponse.empty())
+    {
+        log<level::ERR>("Error reading mapper response",
+                        entry("PATH=%s", SOFTWARE_OBJPATH),
+                        entry("INTERFACE=%s", VERSION_IFACE));
+        return -1;
+    }
+
+    for (const auto& resp : mapperResponse)
+    {
+        // Version id is the last item in the path
+        auto pos = resp.rfind("/");
+        if (pos == std::string::npos)
+        {
+            log<level::ERR>("No version id found in object path",
+                    entry("OBJPATH=%s", resp));
+            return -1;
+        }
+
+        auto versionId = std::stoi(resp.substr(pos + 1), nullptr, 16);
+        if (updater->activations.find(versionId) == updater->activations.end())
+        {
+            updater->activations.insert(std::make_pair(
+                    versionId,
+                    std::make_unique<Activation>(
+                            updater->busItem,
+                            resp)));
+        }
+    }
     return 0;
 }