monitor: Event logs for nonfunc fan sensors
This commit adds the code to create event logs calling out the fan when
fan sensors have been nonfunctional for a certain amount of time.
This functionality is configured in the JSON, and will only be enabled
if the 'fault_handling' JSON section is present. It uses the following
new JSON parameters:
nonfunc_rotor_error_delay (per fan):
This says how many seconds a fan sensor must be nonfunctional before the
event log will be created.
num_nonfunc_rotors_before_error (under fault_handling):
This specifies how many nonfunctional fan rotors there must be at the
same time before an event log with an error severity is created for the
rotor. When there are fewer than this many nonfunctional rotors, then
event logs with an informational severity will be created.
A new FanError class is used to create the event logs. It adds the
Logger output as FFDC, plus any JSON data that is passed in with the
commit() API. It uses CALLOUT_INVENTORY_PATH in the AdditionalData
property to specify the faulted fan FRU.
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I365114357580b4f38ec943a769c1ce7f695b51ab
diff --git a/monitor/fan_error.hpp b/monitor/fan_error.hpp
new file mode 100644
index 0000000..f190758
--- /dev/null
+++ b/monitor/fan_error.hpp
@@ -0,0 +1,166 @@
+#pragma once
+
+#include "utility.hpp"
+
+#include <nlohmann/json.hpp>
+#include <xyz/openbmc_project/Logging/Entry/server.hpp>
+
+#include <filesystem>
+#include <string>
+#include <tuple>
+
+namespace phosphor::fan::monitor
+{
+
+/**
+ * @class FFDCFile
+ *
+ * This class holds a file that is used for event log FFDC
+ * which needs a file descriptor as input. The file is
+ * deleted upon destruction.
+ */
+class FFDCFile
+{
+ public:
+ FFDCFile() = delete;
+ FFDCFile(const FFDCFile&) = delete;
+ FFDCFile& operator=(const FFDCFile&) = delete;
+ FFDCFile(FFDCFile&&) = delete;
+ FFDCFile& operator=(FFDCFile&&) = delete;
+
+ /**
+ * @brief Constructor
+ *
+ * Opens the file and saves the descriptor
+ *
+ * @param[in] name - The filename
+ */
+ explicit FFDCFile(const std::filesystem::path& name);
+
+ /**
+ * @brief Destructor - Deletes the file
+ */
+ ~FFDCFile()
+ {
+ std::filesystem::remove(_name);
+ }
+
+ /**
+ * @brief Returns the file descriptor
+ *
+ * @return int - The descriptor
+ */
+ int fd()
+ {
+ return _fd();
+ }
+
+ private:
+ /**
+ * @brief The file descriptor holder
+ */
+ util::FileDescriptor _fd;
+
+ /**
+ * @brief The filename
+ */
+ const std::filesystem::path _name;
+};
+
+/**
+ * @class FanError
+ *
+ * This class represents a fan error. It has a commit() interface
+ * that will create the event log with certain FFDC.
+ */
+class FanError
+{
+ public:
+ FanError() = delete;
+ ~FanError() = default;
+ FanError(const FanError&) = delete;
+ FanError& operator=(const FanError&) = delete;
+ FanError(FanError&&) = delete;
+ FanError& operator=(FanError&&) = delete;
+
+ /**
+ * @brief Constructor
+ *
+ * @param[in] error - The error name, like
+ * xyz.openbmc_project.Fan.Error.Fault
+ * @param[in] fan - The failing fan's inventory path
+ * @param[in] sensor - The failing sensor's inventory path. Can be empty
+ * if the error is for the FRU and not the sensor.
+ * @param[in] severity - The severity of the error
+ */
+ FanError(const std::string& error, const std::string& fan,
+ const std::string& sensor,
+ sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level
+ severity) :
+ _errorName(error),
+ _fanName(fan), _sensorName(sensor),
+ _severity(
+ sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
+ severity))
+ {}
+
+ /**
+ * @brief Commits the error by calling the D-Bus method to create
+ * the event log.
+ *
+ * The FFDC is passed in here so that if an error is committed
+ * more than once it can have up to date FFDC.
+ *
+ * @param[in] jsonFFDC - Free form JSON data that should be sent in as
+ * FFDC.
+ */
+ void commit(const nlohmann::json& jsonFFDC);
+
+ private:
+ /**
+ * @brief Returns an FFDCFile holding the Logger contents
+ *
+ * @return std::unique_ptr<FFDCFile> - The file object
+ */
+ std::unique_ptr<FFDCFile> makeLogFFDCFile();
+
+ /**
+ * @brief Returns an FFDCFile holding the contents of the JSON FFDC
+ *
+ * @param[in] ffdcData - The JSON data to write to a file
+ *
+ * @return std::unique_ptr<FFDCFile> - The file object
+ */
+ std::unique_ptr<FFDCFile> makeJsonFFDCFile(const nlohmann::json& ffdcData);
+
+ /**
+ * @brief Create and returns the AdditionalData property to use for the
+ * event log.
+ *
+ * @return map<string, string> - The AdditionalData contents
+ */
+ std::map<std::string, std::string> getAdditionalData();
+
+ /**
+ * @brief The error name (The event log's 'Message' property)
+ */
+ const std::string _errorName;
+
+ /**
+ * @brief The inventory name of the failing fan
+ */
+ const std::string _fanName;
+
+ /**
+ * @brief The inventory name of the failing sensor, if there is one.
+ */
+ const std::string _sensorName;
+
+ /**
+ * @brief The severity of the event log. This is the string
+ * representation of the Entry::Level property.
+ */
+ const std::string _severity;
+};
+
+} // namespace phosphor::fan::monitor