associations: Add conditions support
Allow there to be multiple associations files that are selected based on
an inventory property condition specified inside of them. The file(s)
needs to be located in the same directory as the default associations
file, but can have any name as long as it ends in .json. If a
conditional associations file is found, the default associations file is
ignored.
For example:
{
"condition":
{
"path": "system/chassis/motherboard",
"interface": "xyz.openbmc_project.Inventory.Decorator.Asset",
"property": "Model",
"values": [
"ModelA",
"ModelB"
]
},
"associations":
[
// The same associations syntax as described above.
]
}
This states that the associations in this file are valid if the
motherboard inventory item has a Model property with a value of either
ModelA or ModelB.
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: Ib0f32815dee718ea268715896b5470ed2f25119e
diff --git a/association_manager.hpp b/association_manager.hpp
index 2be0058..eda7e05 100644
--- a/association_manager.hpp
+++ b/association_manager.hpp
@@ -2,8 +2,14 @@
#include "config.h"
+#include "types.hpp"
+
+#include <nlohmann/json.hpp>
#include <xyz/openbmc_project/Association/Definitions/server.hpp>
+#include <any>
+#include <filesystem>
+
namespace phosphor
{
namespace inventory
@@ -47,6 +53,16 @@
class Manager
{
public:
+ struct Condition
+ {
+ std::string path;
+ std::string interface;
+ std::string property;
+ std::vector<InterfaceVariantType> values;
+ std::filesystem::path file;
+ InterfaceVariantType actualValue;
+ };
+
Manager() = delete;
~Manager() = default;
Manager(const Manager&) = delete;
@@ -95,13 +111,69 @@
return _associations;
}
+ /**
+ * @brief Returns the list of conditions
+ *
+ * @return vector<Condition>& - The conditions
+ */
+ std::vector<Condition>& getConditions()
+ {
+ return _conditions;
+ }
+
+ /**
+ * @brief Says if there are conditions that need to be met
+ * before an associations file is valid.
+ *
+ * @return bool - If there are pending conditions
+ */
+ bool pendingCondition() const
+ {
+ return !_conditions.empty();
+ }
+
+ /**
+ * @brief Checks if a pending condition is satisfied based on the
+ * path, interface, and property value of the object passed
+ * in.
+ *
+ * If it is valid, it will load the associations pointed to
+ * by that condition and erase the _conditions vector as
+ * there are no longer any pending conditions.
+ *
+ * @param[in] objectPath - The D-Bus path of the object to check
+ * @param[in] in object - The interface and properties of the object
+ *
+ * @return bool - If the object matched a condition
+ */
+ bool conditionMatch(const sdbusplus::message::object_path& objectPath,
+ const Object& object);
+
+ /**
+ * @brief Checks if a pending condition is satisfied based on if the
+ * actualValue field in the condition matches one of the values
+ * in the values field.
+ *
+ * The actualValue field was previously set by code based on the
+ * real property value of the specified interface on the specified
+ * path.
+ *
+ * If it is valid, it will load the associations pointed to
+ * by that condition and erase the _conditions vector as
+ * there are no longer any pending conditions.
+ *
+ * @return bool - If a condition was met
+ */
+ bool conditionMatch();
+
private:
/**
- * @brief Loads the association YAML into the _associations data
- * structure. This file is optional, so if it doesn't exist
- * it will just not load anything.
+ * @brief Loads the association JSON into the _associations data
+ * structure.
+ *
+ * @param[in] json - The associations JSON
*/
- void load();
+ void load(const nlohmann::json& json);
/**
* @brief Creates an instance of an org.openbmc.Associations
@@ -120,6 +192,13 @@
const std::string& reverseType, bool deferSignal);
/**
+ * @brief Looks for all JSON files in the associations directory that
+ * contain a valid association condition, and loads the
+ * conditions into the _conditions vector.
+ */
+ bool loadConditions();
+
+ /**
* @brief The map of association data that is loaded from its
* JSON definition. Association D-Bus objects will be
* created from this data.
@@ -140,12 +219,17 @@
/**
* @brief The path to the associations JSON File.
*/
- const std::string _jsonFile;
+ const std::filesystem::path _jsonFile;
/**
* A list of the inventory association paths that have already been handled.
*/
std::vector<std::string> _handled;
+
+ /**
+ * @brief Conditions that specify when an associations file is valid.
+ */
+ std::vector<Condition> _conditions;
};
} // namespace associations