Improve error handling for exceptions and asserts

The phosphor-psu-code-manager application currently exits abnormally due
to the following conditions:
* Uncaught exception
* False assert() statement

An abnormal exit can result in a core dump and/or a BMC dump. It also
causes the service to be restarted. If the failure condition remains,
the restarts will fail repeatedly, and systemd will stop trying to start
the service.

Improve error handling for exceptions in the following ways:
* Add try/catch blocks to the following locations:
  * Code that calls functions that throw and needs to handle exceptions.
    * For example, code looping over PSU objects may need to handle an
      exception for one PSU and then continue to the remaining PSUs.
  * D-Bus PropertiesChanged and InterfacesAdded event handlers.
    * Do not allow exceptions to escape to the sdbusplus stack frames.
  * main()
    * Last line of defense; catching avoids a core dump.
* Write exception error message to the journal if appropriate

Replace assert statements with exceptions or error messages to the
journal.

Tested:
* Tested all modified functions/methods.
* Verified that all exceptions were caught and logged to the journal if
  appropriate.
* Verified that asserts were replaced by exceptions and logging.
* See complete test plan at
  https://gist.github.com/smccarney/b4bf568639fedd269c9737234fa2803d

Change-Id: I933386e94f43a915b301d6aef7d91691816a0548
Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
diff --git a/src/item_updater.hpp b/src/item_updater.hpp
index e8a489c..e4d7b99 100644
--- a/src/item_updater.hpp
+++ b/src/item_updater.hpp
@@ -14,6 +14,10 @@
 #include <xyz/openbmc_project/Collection/DeleteAll/server.hpp>
 
 #include <filesystem>
+#include <map>
+#include <string>
+#include <variant>
+#include <vector>
 
 class TestItemUpdater;
 
@@ -54,14 +58,14 @@
         versionMatch(
             bus,
             MatchRules::interfacesAdded() + MatchRules::path(SOFTWARE_OBJPATH),
-            std::bind(std::mem_fn(&ItemUpdater::createActivation), this,
-                      std::placeholders::_1)),
+            std::bind(std::mem_fn(&ItemUpdater::onVersionInterfacesAddedMsg),
+                      this, std::placeholders::_1)),
         psuInterfaceMatch(
             bus,
             MatchRules::interfacesAdded() +
                 MatchRules::path("/xyz/openbmc_project/inventory") +
                 MatchRules::sender("xyz.openbmc_project.Inventory.Manager"),
-            std::bind(std::mem_fn(&ItemUpdater::onPSUInterfaceAdded), this,
+            std::bind(std::mem_fn(&ItemUpdater::onPSUInterfacesAdded), this,
                       std::placeholders::_1))
     {
         processPSUImageAndSyncToLatest();
@@ -109,25 +113,37 @@
                       const std::string& psuInventoryPath) override;
 
   private:
+    using Properties =
+        std::map<std::string, utils::UtilsInterface::PropertyType>;
+    using InterfacesAddedMap =
+        std::map<std::string,
+                 std::map<std::string, std::variant<bool, std::string>>>;
+
     /** @brief Callback function for Software.Version match.
-     *  @details Creates an Activation D-Bus object.
      *
      * @param[in]  msg       - Data associated with subscribed signal
      */
-    void createActivation(sdbusplus::message_t& msg);
+    void onVersionInterfacesAddedMsg(sdbusplus::message_t& msg);
 
-    using Properties =
-        std::map<std::string, utils::UtilsInterface::PropertyType>;
+    /** @brief Called when new Software.Version interfaces are found
+     *  @details Creates an Activation D-Bus object if appropriate
+     *           Throws an exception if an error occurs.
+     *
+     * @param[in]  path       - D-Bus object path
+     * @param[in]  interfaces - D-Bus interfaces that were added
+     */
+    void onVersionInterfacesAdded(const std::string& path,
+                                  const InterfacesAddedMap& interfaces);
 
     /** @brief Callback function for PSU inventory match.
-     *  @details Update an Activation D-Bus object for PSU inventory.
      *
      * @param[in]  msg       - Data associated with subscribed signal
      */
     void onPsuInventoryChangedMsg(sdbusplus::message_t& msg);
 
-    /** @brief Callback function for PSU inventory match.
+    /** @brief Called when a PSU inventory object has changed
      *  @details Update an Activation D-Bus object for PSU inventory.
+     *           Throws an exception if an error occurs.
      *
      * @param[in]  psuPath - The PSU inventory path
      * @param[in]  properties - The updated properties
@@ -186,8 +202,21 @@
     /** @brief Create PSU Version from stored images */
     void processStoredImage();
 
-    /** @brief Scan a directory and create PSU Version from stored images */
-    void scanDirectory(const fs::path& p);
+    /** @brief Scan a directory and create PSU Version from stored images
+     *  @details Throws an exception if an error occurs
+     *
+     * @param[in] dir Directory path to scan
+     */
+    void scanDirectory(const fs::path& dir);
+
+    /** @brief Find the PSU model subdirectory within the specified directory
+     *  @details Throws an exception if an error occurs
+     *
+     * @param[in] dir Directory path to search
+     *
+     * @return Subdirectory path, or an empty path if none found
+     */
+    fs::path findModelDirectory(const fs::path& dir);
 
     /** @brief Get the versionId of the latest PSU version */
     std::optional<std::string> getLatestVersionId();
@@ -200,12 +229,12 @@
 
     /** @brief Callback function for interfaces added signal.
      *
-     * This method is called when a new interface is added. It updates the
-     * internal status map and process the new PSU if it's present.
+     * This method is called when new interfaces are added. It updates the
+     * internal status map and processes the new PSU if it's present.
      *
      *  @param[in] msg - Data associated with subscribed signal
      */
-    void onPSUInterfaceAdded(sdbusplus::message_t& msg);
+    void onPSUInterfacesAdded(sdbusplus::message_t& msg);
 
     /**
      * @brief Handles the processing of PSU images.