boot-block: create d-bus block object on callout
If the QuiesceOnHwError is set and a callout is present in the Entry
then create the new block object and the
xyz.openbmc_project.Logging.ErrorBlocksTransition interface.
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
Change-Id: I9aea289ab7cc8dc7649820ff54edc8c04ecb3ef5
diff --git a/elog_block.hpp b/elog_block.hpp
new file mode 100644
index 0000000..e246fa9
--- /dev/null
+++ b/elog_block.hpp
@@ -0,0 +1,45 @@
+#pragma once
+
+#include "xyz/openbmc_project/Logging/ErrorBlocksTransition/server.hpp"
+
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/server/object.hpp>
+
+namespace phosphor
+{
+namespace logging
+{
+
+using BlockIface = sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::Logging::server::ErrorBlocksTransition>;
+
+/** @class Block
+ * @brief OpenBMC logging Block implementation.
+ * @details A concrete implementation for the
+ * xyz.openbmc_project.Logging.ErrorBlocksTransition DBus API
+ */
+class Block : public BlockIface
+{
+ public:
+ Block() = delete;
+ Block(const Block&) = delete;
+ Block& operator=(const Block&) = delete;
+ Block(Block&&) = delete;
+ Block& operator=(Block&&) = delete;
+ virtual ~Block() = default;
+
+ /** @brief Constructor to put object onto bus at a dbus path.
+ * @param[in] bus - Bus to attach to.
+ * @param[in] path - Path to attach at.
+ * @param[in] entryId - Distinct ID of the error.
+ */
+ Block(sdbusplus::bus::bus& bus, const std::string& path, uint32_t entryId) :
+ BlockIface(bus, path.c_str()), entryId(entryId){};
+
+ uint32_t entryId;
+
+ private:
+};
+
+} // namespace logging
+} // namespace phosphor
diff --git a/log_manager.cpp b/log_manager.cpp
index cf2a795..72a8f3c 100644
--- a/log_manager.cpp
+++ b/log_manager.cpp
@@ -291,7 +291,17 @@
logging::log<logging::level::INFO>(
"QuiesceOnError set and callout present");
+
+ std::string blockPath(OBJ_LOGGING);
+ blockPath += "/block";
+ blockPath += std::to_string(entry.id());
+ auto blockObj =
+ std::make_unique<Block>(this->busLog, blockPath, entry.id());
+ this->blockingErrors.push_back(std::move(blockObj));
+
// TODO in later commit in this series
+ // Call systemd to quiesce host
+ // Ensure blockingErrors removes entries when log resolved
}
void Manager::doExtensionLogCreate(const Entry& entry, const FFDCEntries& ffdc)
diff --git a/log_manager.hpp b/log_manager.hpp
index b24a7f3..8f8ff82 100644
--- a/log_manager.hpp
+++ b/log_manager.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include "elog_block.hpp"
#include "elog_entry.hpp"
#include "xyz/openbmc_project/Collection/DeleteAll/server.hpp"
#include "xyz/openbmc_project/Logging/Create/server.hpp"
@@ -131,6 +132,15 @@
*/
int getInfoErrSize();
+ /** @brief Returns the number of blocking errors
+ *
+ * @return int - count of blocking errors
+ */
+ int getBlockingErrSize()
+ {
+ return blockingErrors.size();
+ }
+
sdbusplus::bus::bus& getBus()
{
return busLog;
@@ -265,6 +275,9 @@
/** @brief The BMC firmware version */
const std::string fwVersion;
+
+ /** @brief Array of blocking errors */
+ std::vector<std::unique_ptr<Block>> blockingErrors;
};
} // namespace internal
diff --git a/test/elog_quiesce_test.cpp b/test/elog_quiesce_test.cpp
index a29dc3e..3eb2a3d 100644
--- a/test/elog_quiesce_test.cpp
+++ b/test/elog_quiesce_test.cpp
@@ -78,6 +78,70 @@
EXPECT_EQ(manager.isCalloutPresent(elog), true);
}
+// Test that no blocking errors are created when no callout
+TEST_F(TestQuiesceOnError, testNoBlockingErrorsCreated)
+{
+ uint32_t id = 99;
+ uint64_t timestamp{100};
+ std::string message{"test error"};
+ std::string fwLevel{"level42"};
+ std::vector<std::string> testData{"no", "callout"};
+ phosphor::logging::AssociationList associations{};
+
+ Entry elog{mockedBus,
+ std::string(OBJ_ENTRY) + '/' + std::to_string(id),
+ id,
+ timestamp,
+ Entry::Level::Informational,
+ std::move(message),
+ std::move(testData),
+ std::move(associations),
+ fwLevel,
+ manager};
+
+ manager.checkQuiesceOnError(elog);
+ EXPECT_EQ(manager.getBlockingErrSize(), 0);
+}
+
+// Test that a blocking error is created on entry with callout
+TEST_F(TestQuiesceOnError, testBlockingErrorsCreated)
+{
+ uint32_t id = 100;
+ uint64_t timestamp{100};
+ std::string message{"test error"};
+ std::string fwLevel{"level42"};
+ std::vector<std::string> testData{
+ "CALLOUT_INVENTORY_PATH=/xyz/openbmc_project/inventory/system/chassis/"
+ "motherboard/powersupply0/"};
+ phosphor::logging::AssociationList associations{};
+
+ // Ensure D-Bus object created for this blocking error
+ // First allow any number of sd_bus_emit_object_added calls
+ EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(testing::_, testing::_))
+ .Times(testing::AnyNumber());
+ // Second verify the new block100 object is created once
+ EXPECT_CALL(sdbusMock,
+ sd_bus_emit_object_added(
+ testing::_, testing::HasSubstr(
+ "/xyz/openbmc_project/logging/block100")))
+ .Times(1);
+
+ Entry elog{mockedBus,
+ std::string(OBJ_ENTRY) + '/' + std::to_string(id),
+ id,
+ timestamp,
+ Entry::Level::Informational,
+ std::move(message),
+ std::move(testData),
+ std::move(associations),
+ fwLevel,
+ manager};
+
+ manager.checkQuiesceOnError(elog);
+ // Created error with callout so expect a blocking error now
+ EXPECT_EQ(manager.getBlockingErrSize(), 1);
+}
+
} // namespace test
} // namespace logging
} // namespace phosphor