Refactor D-Bus object

- The intent behind this commit is to refactor D-Bus, and abstract
  the bus, getService, getProperty and other methods into the utils
  file, and other file operations D-Bus only need to include
  uitls.hpp.

- We can also continue to add other general methods such as
  setPropery, getSubTree in the utils file in the future.

- Also, removed redundant files(occ_finder.hpp and occ_finder.cpp).

Tested: built openpower-occ-control successfully and worked.

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I53e61e30a76173c154a9f47fc122936468abbc4b
diff --git a/Makefile.am b/Makefile.am
index babbe6c..f3863dd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,7 +6,6 @@
 	powercap.hpp \
 	occ_errors.hpp \
 	occ_events.hpp \
-	occ_finder.hpp \
 	occ_presence.hpp \
 	occ_command.hpp \
 	utils.hpp
@@ -28,7 +27,6 @@
 	occ_command.cpp \
 	powercap.cpp \
 	org/open_power/OCC/Device/error.cpp \
-	occ_finder.cpp \
 	i2c_occ.cpp \
 	utils.cpp
 
diff --git a/app.cpp b/app.cpp
index 260e27b..a26fa3c 100644
--- a/app.cpp
+++ b/app.cpp
@@ -3,6 +3,7 @@
 #include "elog-errors.hpp"
 #include "occ_events.hpp"
 #include "occ_manager.hpp"
+#include "utils.hpp"
 
 #include <org/open_power/OCC/Device/error.hpp>
 #include <phosphor-logging/elog.hpp>
@@ -17,7 +18,7 @@
 
 int main(int argc, char* argv[])
 {
-    auto bus = sdbusplus::bus::new_default();
+    auto& bus = open_power::occ::utils::getBus();
 
     // Need sd_event to watch for OCC device errors
     sd_event* event = nullptr;
@@ -34,7 +35,7 @@
     bus.attach_event(eventP.get(), SD_EVENT_PRIORITY_NORMAL);
 
     sdbusplus::server::manager::manager objManager(bus, OCC_CONTROL_ROOT);
-    open_power::occ::Manager mgr(bus, eventP);
+    open_power::occ::Manager mgr(eventP);
 
     // Claim the bus since all the house keeping is done now
     bus.request_name(OCC_CONTROL_BUSNAME);
diff --git a/occ_command.cpp b/occ_command.cpp
index e9b03a9..d07c06f 100644
--- a/occ_command.cpp
+++ b/occ_command.cpp
@@ -56,13 +56,12 @@
     }
 }
 
-OccCommand::OccCommand(uint8_t instance, sdbusplus::bus::bus& bus,
-                       const char* path) :
-    occInstance(instance),
-    path(path),
+OccCommand::OccCommand(uint8_t instance, const char* path) :
+    occInstance(instance), path(path),
     devicePath(OCC_DEV_PATH + std::to_string((this->path.back() - '0') + 1)),
     activeStatusSignal(
-        bus, sdbusRule::propertiesChanged(path, "org.open_power.OCC.Status"),
+        utils::getBus(),
+        sdbusRule::propertiesChanged(path, "org.open_power.OCC.Status"),
         std::bind(std::mem_fn(&OccCommand::activeStatusEvent), this,
                   std::placeholders::_1))
 {
diff --git a/occ_command.hpp b/occ_command.hpp
index 8420e3b..2c925f6 100644
--- a/occ_command.hpp
+++ b/occ_command.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "occ_errors.hpp"
+#include "utils.hpp"
 
 #include <org/open_power/OCC/PassThrough/server.hpp>
 #include <sdbusplus/bus.hpp>
@@ -47,10 +48,9 @@
     /** @brief Ctor to set up which OCC the command will go to
      *
      *  @param[in] instance - OCC instance
-     *  @param[in] bus - Bus to attach to
      *  @param[in] path - Path to attach at
      */
-    OccCommand(uint8_t instance, sdbusplus::bus::bus& bus, const char* path);
+    OccCommand(uint8_t instance, const char* path);
 
     /** @brief Dtor to clean up and close device */
     ~OccCommand()
diff --git a/occ_finder.cpp b/occ_finder.cpp
deleted file mode 100644
index 3279632..0000000
--- a/occ_finder.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-#include "config.h"
-
-#include "occ_finder.hpp"
-
-#include <algorithm>
-#include <experimental/filesystem>
-#include <iterator>
-#include <phosphor-logging/elog-errors.hpp>
-#include <phosphor-logging/log.hpp>
-#include <sdbusplus/server.hpp>
-#include <xyz/openbmc_project/Common/error.hpp>
-namespace open_power
-{
-namespace occ
-{
-namespace finder
-{
-
-using namespace phosphor::logging;
-
-constexpr auto toChar(size_t c)
-{
-    constexpr auto map = "0123456789abcdef";
-    return map[c];
-}
-
-template <typename T>
-T getDbusProperty(sdbusplus::bus::bus& bus, const std::string& service,
-                  const std::string& objPath, const std::string& interface,
-                  const std::string& property)
-{
-    using namespace sdbusplus::xyz::openbmc_project::Common::Error;
-
-    constexpr auto PROPERTY_INTF = "org.freedesktop.DBus.Properties";
-
-    auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
-                                      PROPERTY_INTF, "Get");
-    method.append(interface, property);
-
-    auto reply = bus.call(method);
-    if (reply.is_method_error())
-    {
-        log<level::ERR>("Failed to get property",
-                        entry("PROPERTY=%s", property.c_str()),
-                        entry("PATH=%s", objPath.c_str()),
-                        entry("INTERFACE=%s", interface.c_str()));
-        elog<InternalFailure>();
-    }
-
-    std::variant<T> value;
-    reply.read(value);
-
-    return std::get<T>(value);
-}
-
-std::vector<std::string> get(sdbusplus::bus::bus& bus)
-{
-    namespace fs = std::experimental::filesystem;
-    using Path = std::string;
-    using Service = std::string;
-    using Interface = std::string;
-    using Interfaces = std::vector<Interface>;
-
-    auto mapper =
-        bus.new_method_call("xyz.openbmc_project.ObjectMapper",
-                            "/xyz/openbmc_project/object_mapper",
-                            "xyz.openbmc_project.ObjectMapper", "GetSubTree");
-
-    auto depth = 0;
-    Path path = CPU_SUBPATH;
-    Interfaces interfaces{
-        "xyz.openbmc_project.Inventory.Item",
-        "xyz.openbmc_project.State.Decorator.OperationalStatus"};
-
-    mapper.append(path);
-    mapper.append(depth);
-    mapper.append(interfaces);
-
-    auto result = bus.call(mapper);
-    if (result.is_method_error())
-    {
-        // It's okay to not have inventory, for example at BMC standby
-        return {};
-    }
-
-    using MapperResponse = std::map<Path, std::map<Service, Interfaces>>;
-    MapperResponse response;
-    result.read(response);
-    if (response.empty())
-    {
-        // It's okay to not have inventory, for example at BMC standby
-        return {};
-    }
-
-    std::vector<std::string> occs;
-    for (auto count = 0; count < MAX_CPUS; ++count)
-    {
-        fs::path p(path);
-        p /= std::string(CPU_NAME) + toChar(count);
-
-        auto entry = response.find(p.string());
-        if (response.end() != entry)
-        {
-            Criteria match{};
-            match.emplace_back(std::make_tuple(
-                "xyz.openbmc_project.Inventory.Item", "Present", true));
-
-            // Select only if the CPU is marked 'Present'.
-            // Local variable to make it readable
-            auto path = entry->first;
-            auto service = entry->second.begin()->first;
-            if (matchCriteria(bus, path, service, match))
-            {
-                occs.emplace_back(std::string(OCC_NAME) + toChar(count));
-            }
-        }
-    }
-
-    return occs;
-}
-
-bool matchCriteria(sdbusplus::bus::bus& bus, const std::string& path,
-                   const std::string& service, const Criteria& match)
-{
-    for (const auto& iter : match)
-    {
-        auto result = getDbusProperty<bool>(
-            bus, service, path, std::get<0>(iter), std::get<1>(iter));
-        if (result != std::get<2>(iter))
-        {
-            return false;
-        }
-    }
-    return true;
-}
-
-} // namespace finder
-} // namespace occ
-} // namespace open_power
diff --git a/occ_finder.hpp b/occ_finder.hpp
deleted file mode 100644
index 59b5984..0000000
--- a/occ_finder.hpp
+++ /dev/null
@@ -1,61 +0,0 @@
-#pragma once
-
-#include <sdbusplus/bus.hpp>
-#include <string>
-#include <vector>
-
-namespace open_power
-{
-namespace occ
-{
-namespace finder
-{
-
-// Map of property and interface
-// This is used to filter the OCCs based on the property value
-using Interface = std::string;
-using Property = std::string;
-
-using Value = bool;
-using Match = std::tuple<Interface, Property, Value>;
-using Criteria = std::vector<Match>;
-
-/** @brief Get OCC objects on the system by mapping them to CPU inventory
- * @returns vector of occ objects, such as occ0, occ1, and so on.
- *
- * @param[in] bus - sdbusplus handler
- */
-std::vector<std::string> get(sdbusplus::bus::bus& bus);
-
-/** @brief Returns true if the inventory item matches the criteria
- *
- *  @param[in] bus      - sdbusplus handler
- *  @param[in] path     - D-Bus path
- *  @param[in] service  - D-Bus service name
- *  @param[in] match    - Criteria match vector
- *
- *  @return true on match, false otherwise
- */
-bool matchCriteria(sdbusplus::bus::bus& bus, const std::string& path,
-                   const std::string& service, const Criteria& match);
-
-/** @brief Gets the value associated with the given object
- *         and the interface.
- *
- *  @param[in] bus       - sdbusplus handler
- *  @param[in] service   - D-Bus service name.
- *  @param[in] objPath   - D-Bus object path.
- *  @param[in] interface - D-Bus interface.
- *  @param[in] property  - Name of the property.
- *
- *  @return Value of the property
- */
-
-template <typename T>
-T getDbusProperty(sdbusplus::bus::bus& bus, const std::string& service,
-                  const std::string& objPath, const std::string& interface,
-                  const std::string& property);
-
-} // namespace finder
-} // namespace occ
-} // namespace open_power
diff --git a/occ_manager.cpp b/occ_manager.cpp
index fc9a112..4b209da 100644
--- a/occ_manager.cpp
+++ b/occ_manager.cpp
@@ -3,7 +3,6 @@
 #include "occ_manager.hpp"
 
 #include "i2c_occ.hpp"
-#include "occ_finder.hpp"
 #include "utils.hpp"
 
 #include <experimental/filesystem>
@@ -50,10 +49,10 @@
     auto path = fs::path(OCC_CONTROL_ROOT) / occ;
 
     passThroughObjects.emplace_back(
-        std::make_unique<PassThrough>(bus, path.c_str()));
+        std::make_unique<PassThrough>(path.c_str()));
 
     statusObjects.emplace_back(std::make_unique<Status>(
-        bus, event, path.c_str(), *this,
+        event, path.c_str(), *this,
         std::bind(std::mem_fn(&Manager::statusCallBack), this,
                   std::placeholders::_1)
 #ifdef PLDM
@@ -67,7 +66,7 @@
     if (!pcap)
     {
         pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
-            bus, *statusObjects.front());
+            *statusObjects.front());
     }
 }
 
@@ -128,11 +127,11 @@
         name = std::string(OCC_NAME) + '_' + name;
         auto path = fs::path(OCC_CONTROL_ROOT) / name;
         statusObjects.emplace_back(
-            std::make_unique<Status>(bus, event, path.c_str(), *this));
+            std::make_unique<Status>(event, path.c_str(), *this));
     }
     // The first device is master occ
     pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
-        bus, *statusObjects.front(), occMasterName);
+        *statusObjects.front(), occMasterName);
 }
 #endif
 
diff --git a/occ_manager.hpp b/occ_manager.hpp
index 4db762c..c4218c9 100644
--- a/occ_manager.hpp
+++ b/occ_manager.hpp
@@ -6,6 +6,7 @@
 #include "pldm.hpp"
 #endif
 #include "powercap.hpp"
+#include "utils.hpp"
 
 #include <cstring>
 #include <functional>
@@ -39,11 +40,10 @@
     /** @brief Adds OCC pass-through and status objects on the bus
      *         when corresponding CPU inventory is created.
      *
-     *  @param[in] bus   - handle to the bus
      *  @param[in] event - Unique ptr reference to sd_event
      */
-    Manager(sdbusplus::bus::bus& bus, EventPtr& event) :
-        bus(bus), event(event), pollInterval(defaultPollingInterval),
+    Manager(EventPtr& event) :
+        event(event), pollInterval(defaultPollingInterval),
         sdpEvent(sdeventplus::Event::get_default()),
         _pollTimer(
             std::make_unique<
@@ -52,8 +52,8 @@
 #ifdef PLDM
         ,
         pldmHandle(std::make_unique<pldm::Interface>(
-            bus, std::bind(std::mem_fn(&Manager::updateOCCActive), this,
-                           std::placeholders::_1, std::placeholders::_2)))
+            std::bind(std::mem_fn(&Manager::updateOCCActive), this,
+                      std::placeholders::_1, std::placeholders::_2)))
 #endif
 
     {
@@ -107,9 +107,6 @@
     /** @brief Sends a Heartbeat command to host control command handler */
     void sendHeartBeat();
 
-    /** @brief reference to the bus */
-    sdbusplus::bus::bus& bus;
-
     /** @brief reference to sd_event wrapped in unique_ptr */
     EventPtr& event;
 
diff --git a/occ_pass_through.cpp b/occ_pass_through.cpp
index 11ef469..a53cba4 100644
--- a/occ_pass_through.cpp
+++ b/occ_pass_through.cpp
@@ -21,15 +21,16 @@
 namespace occ
 {
 
-PassThrough::PassThrough(sdbusplus::bus::bus& bus, const char* path) :
-    Iface(bus, path), path(path),
+PassThrough::PassThrough(const char* path) :
+    Iface(utils::getBus(), path), path(path),
     devicePath(OCC_DEV_PATH + std::to_string((this->path.back() - '0') + 1)),
     occInstance(this->path.back() - '0'),
     activeStatusSignal(
-        bus, sdbusRule::propertiesChanged(path, "org.open_power.OCC.Status"),
+        utils::getBus(),
+        sdbusRule::propertiesChanged(path, "org.open_power.OCC.Status"),
         std::bind(std::mem_fn(&PassThrough::activeStatusEvent), this,
                   std::placeholders::_1)),
-    occCmd(occInstance, bus, path)
+    occCmd(occInstance, path)
 {
     // Nothing to do.
 }
diff --git a/occ_pass_through.hpp b/occ_pass_through.hpp
index 0c01ae4..ef31826 100644
--- a/occ_pass_through.hpp
+++ b/occ_pass_through.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "occ_command.hpp"
+#include "utils.hpp"
 
 #include <fmt/core.h>
 
@@ -35,10 +36,9 @@
     PassThrough& operator=(PassThrough&&) = default;
 
     /** @brief Ctor to put pass-through d-bus object on the bus
-     *  @param[in] bus - Bus to attach to
      *  @param[in] path - Path to attach at
      */
-    PassThrough(sdbusplus::bus::bus& bus, const char* path);
+    PassThrough(const char* path);
 
     /** @brief Pass through command to OCC from dbus
      *  @param[in] command - command to pass-through
diff --git a/occ_status.cpp b/occ_status.cpp
index 1bf9330..f4bf8a9 100644
--- a/occ_status.cpp
+++ b/occ_status.cpp
@@ -116,8 +116,9 @@
     constexpr auto CONTROL_HOST_INTF = "org.open_power.Control.Host";
 
     // This will throw exception on failure
-    auto service = getService(bus, CONTROL_HOST_PATH, CONTROL_HOST_INTF);
+    auto service = utils::getService(CONTROL_HOST_PATH, CONTROL_HOST_INTF);
 
+    auto& bus = utils::getBus();
     auto method = bus.new_method_call(service.c_str(), CONTROL_HOST_PATH,
                                       CONTROL_HOST_INTF, "Execute");
     // OCC Reset control command
diff --git a/occ_status.hpp b/occ_status.hpp
index abdc3ed..df2ef51 100644
--- a/occ_status.hpp
+++ b/occ_status.hpp
@@ -4,6 +4,7 @@
 #include "occ_command.hpp"
 #include "occ_device.hpp"
 #include "occ_events.hpp"
+#include "utils.hpp"
 
 #include <functional>
 #include <org/open_power/Control/Host/server.hpp>
@@ -57,7 +58,6 @@
     /** @brief Constructs the Status object and
      *         the underlying device object
      *
-     *  @param[in] bus      - DBus bus to attach to
      *  @param[in] event    - sd_event unique pointer reference
      *  @param[in] path     - DBus object path
      *  @param[in] manager  - OCC manager instance
@@ -67,16 +67,16 @@
      *                             OCC if PLDM is the host communication
      *                             protocol
      */
-    Status(sdbusplus::bus::bus& bus, EventPtr& event, const char* path,
-           const Manager& manager, std::function<void(bool)> callBack = nullptr
+    Status(EventPtr& event, const char* path, const Manager& manager,
+           std::function<void(bool)> callBack = nullptr
 #ifdef PLDM
            ,
            std::function<void(instanceID)> resetCallBack = nullptr
 #endif
            ) :
 
-        Interface(bus, getDbusPath(path).c_str(), true),
-        bus(bus), path(path), callBack(callBack), instance(getInstance(path)),
+        Interface(utils::getBus(), getDbusPath(path).c_str(), true),
+        path(path), callBack(callBack), instance(getInstance(path)),
         device(event,
 #ifdef I2C_OCC
                fs::path(DEV_PATH) / i2c_occ::getI2cDeviceName(path),
@@ -88,7 +88,7 @@
                std::bind(std::mem_fn(&Status::deviceErrorHandler), this,
                          std::placeholders::_1)),
         hostControlSignal(
-            bus,
+            utils::getBus(),
             sdbusRule::type::signal() + sdbusRule::member("CommandComplete") +
                 sdbusRule::path("/org/open_power/control/host0") +
                 sdbusRule::interface("org.open_power.Control.Host") +
@@ -96,10 +96,9 @@
                                        Control::Host::Command::OCCReset)),
             std::bind(std::mem_fn(&Status::hostControlEvent), this,
                       std::placeholders::_1)),
-        occCmd(instance, bus,
-               (fs::path(OCC_CONTROL_ROOT) /
-                (std::string(OCC_NAME) + std::to_string(instance)))
-                   .c_str())
+        occCmd(instance, (fs::path(OCC_CONTROL_ROOT) /
+                          (std::string(OCC_NAME) + std::to_string(instance)))
+                             .c_str())
 #ifdef PLDM
         ,
         resetCallBack(resetCallBack)
@@ -151,9 +150,6 @@
     void readOccState();
 
   private:
-    /** @brief sdbus handle */
-    sdbusplus::bus::bus& bus;
-
     /** @brief OCC dbus object path */
     std::string path;
 
diff --git a/pldm.cpp b/pldm.cpp
index 39437ad..729f292 100644
--- a/pldm.cpp
+++ b/pldm.cpp
@@ -73,6 +73,7 @@
     {

         PdrList pdrs{};

 

+        auto& bus = utils::getBus();

         try

         {

             auto method = bus.new_method_call(

@@ -244,6 +245,7 @@
     {

         PdrList pdrs{};

 

+        auto& bus = utils::getBus();

         try

         {

             auto method = bus.new_method_call(

@@ -284,6 +286,7 @@
 

     uint8_t instanceId{};

 

+    auto bus& = utils::getBus();

     try

     {

         auto method = bus.new_method_call(

diff --git a/pldm.hpp b/pldm.hpp
index 48f80c7..7a93066 100644
--- a/pldm.hpp
+++ b/pldm.hpp
@@ -1,6 +1,7 @@
 #pragma once

 

 #include "occ_status.hpp"

+#include "utils.hpp"

 

 #include <libpldm/pldm.h>

 

@@ -48,17 +49,14 @@
 

     /** @brief Constructs the PLDM Interface object for OCC functions

      *

-     *  @param[in] bus      - reference to systemd bus

      *  @param[in] callBack - callBack handler to invoke when the OCC state

      *                        changes.

      */

     explicit Interface(

-        sdbusplus::bus::bus& bus,

         std::function<bool(open_power::occ::instanceID, bool)> callBack) :

-        bus(bus),

         callBack(callBack),

         pldmEventSignal(

-            bus,

+            utils::getBus(),

             MatchRules::type::signal() +

                 MatchRules::member("StateSensorEvent") +

                 MatchRules::path("/xyz/openbmc_project/pldm") +

@@ -66,7 +64,7 @@
             std::bind(std::mem_fn(&Interface::sensorEvent), this,

                       std::placeholders::_1)),

         hostStateSignal(

-            bus,

+            utils::getBus(),

             MatchRules::propertiesChanged("/xyz/openbmc_project/state/host0",

                                           "xyz.openbmc_project.State.Host"),

             std::bind(std::mem_fn(&Interface::hostStateEvent), this,

@@ -122,9 +120,6 @@
     void resetOCC(open_power::occ::instanceID occInstanceId);

 

   private:

-    /** @brief reference to the systemd bus*/

-    sdbusplus::bus::bus& bus;

-

     /** @brief Callback handler to be invoked when the state of the OCC

      *         changes

      */

diff --git a/powercap.cpp b/powercap.cpp
index 1655982..39c7416 100644
--- a/powercap.cpp
+++ b/powercap.cpp
@@ -23,36 +23,6 @@
 using namespace phosphor::logging;
 namespace fs = std::experimental::filesystem;
 
-std::string PowerCap::getService(std::string path, std::string interface)
-{
-    auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
-                                      MAPPER_INTERFACE, "GetObject");
-
-    mapper.append(path, std::vector<std::string>({interface}));
-    auto mapperResponseMsg = bus.call(mapper);
-
-    if (mapperResponseMsg.is_method_error())
-    {
-        log<level::ERR>("Error in mapper call", entry("PATH=%s", path.c_str()),
-                        entry("INTERFACE=%s", interface.c_str()));
-        // TODO openbmc/openbmc#851 - Once available, throw returned error
-        throw std::runtime_error("Error in mapper call");
-    }
-
-    std::map<std::string, std::vector<std::string>> mapperResponse;
-    mapperResponseMsg.read(mapperResponse);
-    if (mapperResponse.empty())
-    {
-        log<level::ERR>("Error reading mapper response",
-                        entry("PATH=%s", path.c_str()),
-                        entry("INTERFACE=%s", interface.c_str()));
-        // TODO openbmc/openbmc#1712 - Handle empty mapper resp. consistently
-        throw std::runtime_error("Error reading mapper response");
-    }
-
-    return mapperResponse.begin()->first;
-}
-
 uint32_t PowerCap::getOccInput(uint32_t pcap, bool pcapEnabled)
 {
     if (!pcapEnabled)
@@ -68,46 +38,41 @@
 
 uint32_t PowerCap::getPcap()
 {
-    auto settingService = getService(PCAP_PATH, PCAP_INTERFACE);
-
-    auto method =
-        this->bus.new_method_call(settingService.c_str(), PCAP_PATH,
-                                  "org.freedesktop.DBus.Properties", "Get");
-
-    method.append(PCAP_INTERFACE, POWER_CAP_PROP);
-    auto reply = this->bus.call(method);
-
-    if (reply.is_method_error())
+    utils::PropertyValue pcap{};
+    try
     {
-        log<level::ERR>("Error in getPcap prop");
+        pcap = utils::getProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_PROP);
+
+        return std::get<uint32_t>(pcap);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        log<level::ERR>("Failed to get PowerCap property",
+                        entry("ERROR=%s", e.what()),
+                        entry("PATH=%s", PCAP_PATH));
+
         return 0;
     }
-    std::variant<uint32_t> pcap;
-    reply.read(pcap);
-
-    return std::get<uint32_t>(pcap);
 }
 
 bool PowerCap::getPcapEnabled()
 {
-    auto settingService = getService(PCAP_PATH, PCAP_INTERFACE);
-
-    auto method =
-        this->bus.new_method_call(settingService.c_str(), PCAP_PATH,
-                                  "org.freedesktop.DBus.Properties", "Get");
-
-    method.append(PCAP_INTERFACE, POWER_CAP_ENABLE_PROP);
-    auto reply = this->bus.call(method);
-
-    if (reply.is_method_error())
+    utils::PropertyValue pcapEnabled{};
+    try
     {
-        log<level::ERR>("Error in getPcapEnabled prop");
-        return 0;
-    }
-    std::variant<bool> pcapEnabled;
-    reply.read(pcapEnabled);
+        pcapEnabled = utils::getProperty(PCAP_PATH, PCAP_INTERFACE,
+                                         POWER_CAP_ENABLE_PROP);
 
-    return std::get<bool>(pcapEnabled);
+        return std::get<bool>(pcapEnabled);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        log<level::ERR>("Failed to get PowerCapEnable property",
+                        entry("ERROR=%s", e.what()),
+                        entry("PATH=%s", PCAP_PATH));
+
+        return false;
+    }
 }
 
 std::string PowerCap::getPcapFilename(const fs::path& path)
diff --git a/powercap.hpp b/powercap.hpp
index c7861a4..bb4dc8b 100644
--- a/powercap.hpp
+++ b/powercap.hpp
@@ -3,6 +3,7 @@
 #include "config.h"
 
 #include "occ_status.hpp"
+#include "utils.hpp"
 
 #include <experimental/filesystem>
 #include <sdbusplus/bus.hpp>
@@ -34,15 +35,14 @@
      * power cap enable properties.  If a change is detected, and the occ
      * is active, then this object will notify the OCC of the change.
      *
-     * @param[in] bus       - The Dbus bus object
      * @param[in] occStatus - The occ status object
      */
-    PowerCap(sdbusplus::bus::bus& bus, Status& occStatus,
+    PowerCap(Status& occStatus,
              const std::string& occMasterName = OCC_MASTER_NAME) :
-        bus(bus),
-        occMasterName(occMasterName), occStatus(occStatus),
+        occMasterName(occMasterName),
+        occStatus(occStatus),
         pcapMatch(
-            bus,
+            utils::getBus(),
             sdbusRule::member("PropertiesChanged") +
                 sdbusRule::path(
                     "/xyz/openbmc_project/control/host0/power_cap") +
@@ -70,15 +70,6 @@
      */
     void pcapChanged(sdbusplus::message::message& msg);
 
-    /** @brief Look up DBUS service for input path/interface
-     *
-     * @param[in]  path       - DBUS path
-     * @param[in]  path       - DBUS interface
-     *
-     * @return Distinct service name for input path/interface
-     */
-    std::string getService(std::string path, std::string interface);
-
     /** @brief Get the power cap property
      *
      * @return Power cap, 0 on failure to indicate no pcap
@@ -110,9 +101,6 @@
     std::string
         getPcapFilename(const std::experimental::filesystem::path& path);
 
-    /** @brief Reference to sdbus **/
-    sdbusplus::bus::bus& bus;
-
     /** @brief The master occ name */
     std::string occMasterName;
 
diff --git a/test/error_files_tests.cpp b/test/error_files_tests.cpp
index 532818a..c412e63 100644
--- a/test/error_files_tests.cpp
+++ b/test/error_files_tests.cpp
@@ -24,9 +24,8 @@
 {
   public:
     ErrorFiles() :
-        bus(sdbusplus::bus::new_default()), rc(sd_event_default(&event)),
-        pEvent(event), manager(bus, pEvent),
-        status(bus, pEvent, "/dummy1", manager)
+        rc(sd_event_default(&event)), pEvent(event), manager(pEvent),
+        status(pEvent, "/dummy1", manager)
     {
         EXPECT_GE(rc, 0);
         event = nullptr;
@@ -73,7 +72,6 @@
         fs::remove_all(occPath);
     }
 
-    sdbusplus::bus::bus bus;
     sd_event* event;
     int rc;
     open_power::occ::EventPtr pEvent;
diff --git a/test/utest.cpp b/test/utest.cpp
index 39e5250..04fa492 100644
--- a/test/utest.cpp
+++ b/test/utest.cpp
@@ -12,9 +12,8 @@
 {
   public:
     VerifyOccInput() :
-        bus(sdbusplus::bus::new_default()), rc(sd_event_default(&event)),
-        eventP(event), manager(bus, eventP),
-        occStatus(bus, eventP, "/test/path/occ1", manager), pcap(bus, occStatus)
+        rc(sd_event_default(&event)), eventP(event), manager(eventP),
+        occStatus(eventP, "/test/path/occ1", manager), pcap(occStatus)
     {
         EXPECT_GE(rc, 0);
         event = nullptr;
@@ -23,7 +22,6 @@
     {
     }
 
-    sdbusplus::bus::bus bus;
     sd_event* event;
     int rc;
     open_power::occ::EventPtr eventP;
diff --git a/utils.cpp b/utils.cpp
index c68913d..9a412a3 100644
--- a/utils.cpp
+++ b/utils.cpp
@@ -1,3 +1,5 @@
+#include "utils.hpp"
+
 #include <phosphor-logging/elog-errors.hpp>
 #include <sdbusplus/bus.hpp>
 #include <string>
@@ -6,47 +8,73 @@
 {
 namespace occ
 {
-
+namespace utils
+{
 // For throwing exceptions
 using namespace phosphor::logging;
 using InternalFailure =
     sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
 
-std::string getService(sdbusplus::bus::bus& bus, const std::string& path,
-                       const std::string& intf)
+const std::string getService(const std::string& path,
+                             const std::string& interface)
 {
-    auto mapperCall =
-        bus.new_method_call("xyz.openbmc_project.ObjectMapper",
-                            "/xyz/openbmc_project/object_mapper",
-                            "xyz.openbmc_project.ObjectMapper", "GetObject");
 
-    mapperCall.append(path);
-    mapperCall.append(std::vector<std::string>({intf}));
+    using InterfaceList = std::vector<std::string>;
+    std::map<std::string, std::vector<std::string>> mapperResponse;
 
-    auto mapperResponseMsg = bus.call(mapperCall);
+    auto& bus = getBus();
 
+    auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
+                                      MAPPER_IFACE, "GetObject");
+    mapper.append(path, InterfaceList({interface}));
+
+    auto mapperResponseMsg = bus.call(mapper);
     if (mapperResponseMsg.is_method_error())
     {
         log<level::ERR>("ERROR in getting service",
                         entry("PATH=%s", path.c_str()),
-                        entry("INTERFACE=%s", intf.c_str()));
+                        entry("INTERFACE=%s", interface.c_str()));
 
         elog<InternalFailure>();
     }
 
-    std::map<std::string, std::vector<std::string>> mapperResponse;
     mapperResponseMsg.read(mapperResponse);
-
-    if (mapperResponse.begin() == mapperResponse.end())
+    if (mapperResponse.empty())
     {
         log<level::ERR>("ERROR reading mapper response",
                         entry("PATH=%s", path.c_str()),
-                        entry("INTERFACE=%s", intf.c_str()));
+                        entry("INTERFACE=%s", interface.c_str()));
 
         elog<InternalFailure>();
     }
-    return mapperResponse.begin()->first;
+
+    // the value here will be the service name
+    return mapperResponse.cbegin()->first;
 }
 
+const PropertyValue getProperty(const std::string& objectPath,
+                                const std::string& interface,
+                                const std::string& propertyName)
+{
+    PropertyValue value{};
+
+    auto& bus = getBus();
+    auto service = getService(objectPath, interface);
+    if (service.empty())
+    {
+        return value;
+    }
+
+    auto method = bus.new_method_call(service.c_str(), objectPath.c_str(),
+                                      DBUS_PROPERTY_IFACE, "Get");
+    method.append(interface, propertyName);
+
+    auto reply = bus.call(method);
+    reply.read(value);
+
+    return value;
+}
+
+} // namespace utils
 } // namespace occ
 } // namespace open_power
diff --git a/utils.hpp b/utils.hpp
index 7c8b871..1d173a3 100644
--- a/utils.hpp
+++ b/utils.hpp
@@ -6,17 +6,49 @@
 {
 namespace occ
 {
+namespace utils
+{
+constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
+constexpr auto MAPPER_OBJ_PATH = "/xyz/openbmc_project/object_mapper";
+constexpr auto MAPPER_IFACE = "xyz.openbmc_project.ObjectMapper";
+constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
+
+// The value of the property(type: variant, contains some basic types)
+using PropertyValue = std::variant<uint32_t, bool>;
+
+/** @brief Get the bus connection. */
+static auto& getBus()
+{
+    static auto bus = sdbusplus::bus::new_default();
+    return bus;
+}
+
 /**
- * @brief Gets the D-Bus Service name for the input D-Bus path
+ *  @brief Get service name by the path and interface of the DBus.
  *
- * @param[in] bus  -  Bus handler
- * @param[in] path -  Object Path
- * @param[in] intf -  Interface
+ *  @param[in] path      -  D-Bus object path
+ *  @param[in] interface -  D-Bus Interface
  *
- * @return            Service name
- * @error             InternalFailure exception thrown
+ *  @return std::string  -  the D-Bus service name
+ *
  */
-std::string getService(sdbusplus::bus::bus& bus, const std::string& path,
-                       const std::string& intf);
+const std::string getService(const std::string& path,
+                             const std::string& interface);
+
+/** @brief Get property(type: variant)
+ *
+ *  @param[in] objectPath       -   D-Bus object path
+ *  @param[in] interface        -   D-Bus interface
+ *  @param[in] propertyName     -   D-Bus property name
+ *
+ *  @return The value of the property(type: variant)
+ *
+ *  @throw sdbusplus::exception::SdBusError when it fails
+ */
+const PropertyValue getProperty(const std::string& objectPath,
+                                const std::string& interface,
+                                const std::string& propertyName);
+
+} // namespace utils
 } // namespace occ
 } // namespace open_power