inventory : invoke inventory manager's Notify()

Make a call to the inventory manager to construct inventory objects for
OpenPOWER FRUs.

Change-Id: I41988a9299a0509d3120bee1b79fd3aa8176a76c
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
diff --git a/writefru.mako.hpp b/writefru.mako.hpp
index f7a2aa8..7066f9a 100755
--- a/writefru.mako.hpp
+++ b/writefru.mako.hpp
@@ -7,6 +7,8 @@
 
 #include <map>
 #include <iostream>
+#include <sdbusplus/server.hpp>
+#include <log.hpp>
 #include "defines.hpp"
 #include "store.hpp"
 
@@ -17,25 +19,77 @@
 namespace inventory
 {
 
-using Inner = Parsed::mapped_type;
-using Outer = std::map<std::string, Inner>;
+using Property = std::string;
+using Value = sdbusplus::message::variant<bool, int64_t, std::string>;
+using PropertyMap = std::map<Property, Value>;
 
-// TODO: Remove once the call to inventory manager is added
-auto print = [](Outer&& object, const std::string& path)
+using Interface = std::string;
+using InterfaceMap = std::map<Interface, PropertyMap>;
+
+using Object = sdbusplus::message::object_path;
+using ObjectMap = std::map<Object, InterfaceMap>;
+
+using namespace std::string_literals;
+static const auto pimPath = "/xyz/openbmc_project/Inventory"s;
+static const auto pimIntf = "xyz.openbmc_project.Inventory.Manager"s;
+
+/** @brief Get inventory-manager's d-bus service
+ */
+auto getPIMService()
 {
-    std::cout << "\n";
-    std::cout << path << "\n";
-    std::cout << "\n";
-    for(const auto& o : object)
+    auto bus = sdbusplus::bus::new_default();
+    auto mapper =
+        bus.new_method_call(
+            "xyz.openbmc_project.ObjectMapper",
+            "/xyz/openbmc_project/ObjectMapper",
+            "xyz.openbmc_project.ObjectMapper",
+            "GetObject");
+
+    mapper.append(pimPath);
+    mapper.append(std::vector<std::string>({pimIntf}));
+
+    auto result = bus.call(mapper);
+    if(result.is_method_error())
     {
-        std::cout << o.first << "\n";
-        for(const auto& i : o.second)
-        {
-            std::cout << i.first << " : " << i.second << "\n";
-        }
-        std::cout << "\n";
+        throw std::runtime_error("ObjectMapper GetObject failed");
     }
-};
+
+    std::map<std::string, std::vector<std::string>> response;
+    result.read(response);
+    if(response.empty())
+    {
+        throw std::runtime_error("ObjectMapper GetObject bad response");
+    }
+
+    return response.begin()->first;
+}
+
+auto callPIM(ObjectMap&& objects)
+{
+    std::string service;
+
+    try
+    {
+        service = getPIMService();
+        auto bus = sdbusplus::bus::new_default();
+        auto pimMsg = bus.new_method_call(
+                              service.c_str(),
+                              pimPath.c_str(),
+                              pimIntf.c_str(),
+                              "Notify");
+        pimMsg.append(std::move(objects));
+        auto result = bus.call(pimMsg);
+        if(result.is_method_error())
+        {
+            std::cerr << "PIM Notify() failed\n";
+        }
+    }
+    catch (const std::runtime_error& e)
+    {
+        using namespace phosphor::logging;
+        log<level::ERR>(e.what());
+    }
+}
 
 /** @brief API to write parsed VPD to inventory,
  *      for a specifc FRU
@@ -56,33 +110,35 @@
 void writeFru<Fru::${key}>(const Store& vpdStore,
                            const std::string& path)
 {
-    Outer object;
+    ObjectMap objects;
+    InterfaceMap interfaces;
 
     // Inventory manager needs object path, list of interface names to be
     // implemented, and property:value pairs contained in said interfaces
 
-    % for interfaces, properties in fru.iteritems():
+    % for interface, properties in fru.iteritems():
 <%
-        interface = interfaces.split(".")
-        intfName = interface[0] + interface[-1]
+        names = interface.split(".")
+        intfName = names[0] + names[-1]
 %>\
-    Inner ${intfName};
+    PropertyMap ${intfName}Props;
         % for name, value in properties.iteritems():
-            % if fru and interfaces and name and value:
+            % if fru and interface and name and value:
 <%
                 record, keyword = value.split(",")
 %>\
-    ${intfName}["${name}"] =
+    ${intfName}Props["${name}"] =
         vpdStore.get<Record::${record}, record::Keyword::${keyword}>();
             % endif
         % endfor
-    object.emplace("${interfaces}",
-                   std::move(${intfName}));
+    interfaces.emplace("${interface}",
+                       std::move(${intfName}Props));
     % endfor
 
-    // TODO: Need integration with inventory manager, print serialized dbus
-    // object for now.
-    print(std::move(object), path);
+    sdbusplus::message::object_path object(path);
+    objects.emplace(std::move(object), std::move(interfaces));
+
+    callPIM(std::move(objects));
 }
 
 % endfor