summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCheng C Yang <cheng.c.yang@intel.com>2019-10-07 19:17:17 +0300
committerCheng C Yang <cheng.c.yang@intel.com>2019-10-07 19:17:17 +0300
commita0b3fd34a5d6bc48f53b2236249f032b14e0b9b0 (patch)
tree407fd491346bfb6c19a0fb736e4e78eee80565b5
parentf78b98bb6c13f10992d4a21104c9e3f30b466290 (diff)
downloadprovingground-a0b3fd34a5d6bc48f53b2236249f032b14e0b9b0.tar.xz
Implement Power Unit Redundancy
Implement Power Unit Redundancy, when PSU numbers has been changed or any PSU event happen, Power Unit Redundancy event may be triggered. Tested: With the related change on Redfish Event Log in bmcweb, when there are two PSU on the sytem, remove one AC cable on PSU. Then bellow Redfish log will be created. { "@odata.context": "/redfish/v1/$metadata#LogEntry.LogEntry", "@odata.id": "/redfish/v1/Systems/system/LogServices/EventLog/Entries/ 205610", "@odata.type": "#LogEntry.v1_4_0.LogEntry", "Created": "1970-01-03T09:06:50+00:00", "EntryType": "Event", "Id": "205610", "Message": "Power Unit Redundancy lost.", "MessageArgs": [], "MessageId": "OpenBMC.0.1.PowerUnitRedundancyLost", "Name": "System Event Log Entry", "Severity": "Warning" }, { "@odata.context": "/redfish/v1/$metadata#LogEntry.LogEntry", "@odata.id": "/redfish/v1/Systems/system/LogServices/EventLog/Entries/ 205610_1", "@odata.type": "#LogEntry.v1_4_0.LogEntry", "Created": "1970-01-03T09:06:50+00:00", "EntryType": "Event", "Id": "205610_1", "Message": "Power Unit Nonredundant but has sufficient resource.", "MessageArgs": [], "MessageId": "OpenBMC.0.1.PowerUnitNonRedundantSufficient", "Name": "System Event Log Entry", "Severity": "Warning" }, Plug in the AC cable again, the Redfish log will show { "@odata.context": "/redfish/v1/$metadata#LogEntry.LogEntry", "@odata.id": "/redfish/v1/Systems/system/LogServices/EventLog/Entries/ 205621", "@odata.type": "#LogEntry.v1_4_0.LogEntry", "Created": "1970-01-03T09:07:01+00:00", "EntryType": "Event", "Id": "205621", "Message": "Power Unit Redundancy regained.", "MessageArgs": [], "MessageId": "OpenBMC.0.1.PowerUnitRedundancyRegained", "Name": "System Event Log Entry", "Severity": "OK" } Change-Id: Id20a1ccf83497fd5982c9dfee9c972895f395112 Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com>
-rw-r--r--psu-manager/include/cold_redundancy.hpp4
-rw-r--r--psu-manager/src/cold_redundancy.cpp164
2 files changed, 160 insertions, 8 deletions
diff --git a/psu-manager/include/cold_redundancy.hpp b/psu-manager/include/cold_redundancy.hpp
index a8c53b5..8597615 100644
--- a/psu-manager/include/cold_redundancy.hpp
+++ b/psu-manager/include/cold_redundancy.hpp
@@ -49,6 +49,7 @@ class ColdRedundancy
uint8_t psOrder;
uint8_t numberOfPSU = 0;
uint32_t rotationPeriod = 7 * secondsInOneDay;
+ uint8_t redundancyPSURequire = 1;
void startRotateCR(void);
void startCRCheck(void);
@@ -59,6 +60,8 @@ class ColdRedundancy
void putWarmRedundant(void);
void keepAliveCheck(void);
+ void checkRedundancyEvent();
+
std::shared_ptr<sdbusplus::asio::connection>& systemBus;
boost::asio::steady_timer timerRotation;
@@ -67,6 +70,7 @@ class ColdRedundancy
boost::asio::steady_timer warmRedundantTimer2;
boost::asio::steady_timer keepAliveTimer;
boost::asio::steady_timer filterTimer;
+ boost::asio::steady_timer puRedundantTimer;
};
constexpr const uint8_t pmbusCmdCRSupport = 0xd0;
diff --git a/psu-manager/src/cold_redundancy.cpp b/psu-manager/src/cold_redundancy.cpp
index fef4a99..86b23b3 100644
--- a/psu-manager/src/cold_redundancy.cpp
+++ b/psu-manager/src/cold_redundancy.cpp
@@ -31,9 +31,10 @@
static constexpr const bool debug = false;
-static constexpr const std::array<const char*, 2> psuInterfaceTypes = {
+static constexpr const std::array<const char*, 3> psuInterfaceTypes = {
"xyz.openbmc_project.Configuration.pmbus",
- "xyz.openbmc_project.Configuration.PSUPresence"};
+ "xyz.openbmc_project.Configuration.PSUPresence",
+ "xyz.openbmc_project.Configuration.PURedundancy"};
static const constexpr char* inventoryPath =
"/xyz/openbmc_project/inventory/system";
static const constexpr char* eventPath = "/xyz/openbmc_project/State/Decorator";
@@ -52,7 +53,7 @@ ColdRedundancy::ColdRedundancy(
*systemBus, coldRedundancyPath),
timerRotation(io), timerCheck(io), systemBus(systemBus),
warmRedundantTimer1(io), warmRedundantTimer2(io), keepAliveTimer(io),
- filterTimer(io)
+ filterTimer(io), puRedundantTimer(io)
{
io.post([this, &io, &objectServer, &systemBus]() {
createPSU(io, objectServer, systemBus);
@@ -196,26 +197,26 @@ ColdRedundancy::ColdRedundancy(
for (auto& psu : powerSupplies)
{
-
if (psu->name != psuName)
{
continue;
}
- std::string psuEventName = "OperationalStatus";
+ std::string psuEventName = "functional";
auto findEvent = values.find(psuEventName);
if (findEvent != values.end())
{
if (std::get<bool>(findEvent->second))
{
- psu->state = PSUState::acLost;
+ psu->state = PSUState::normal;
}
else
{
- psu->state = PSUState::normal;
+ psu->state = PSUState::acLost;
}
}
}
+ checkRedundancyEvent();
};
for (const char* type : psuInterfaceTypes)
@@ -388,8 +389,30 @@ void ColdRedundancy::createPSU(
"entry in configuration\n";
return;
}
+
if (interface == "xyz.openbmc_project."
- "Configuration.PSUPresence")
+ "Configuration.PURedundancy")
+ {
+ uint64_t* redunancyCount =
+ std::get_if<uint64_t>(
+ &propMap["RedundantCount"]);
+ if (redunancyCount != nullptr)
+ {
+ redundancyPSURequire =
+ static_cast<uint8_t>(
+ *redunancyCount);
+ }
+ else
+ {
+ std::cerr << "Failed to get Power Unit "
+ "Redundancy count, will "
+ "use default value\n";
+ }
+ return;
+ }
+ else if (interface ==
+ "xyz.openbmc_project."
+ "Configuration.PSUPresence")
{
auto psuBus =
std::get_if<uint64_t>(&propMap["Bus"]);
@@ -422,6 +445,16 @@ void ColdRedundancy::createPSU(
"entry in configuration\n";
return;
}
+ for (auto& psu : powerSupplies)
+ {
+ if ((static_cast<uint8_t>(*configBus) ==
+ psu->bus) &&
+ (static_cast<uint8_t>(*configAddress) ==
+ psu->address))
+ {
+ return;
+ }
+ }
powerSupplies.emplace_back(
std::make_unique<PowerSupply>(
@@ -437,6 +470,7 @@ void ColdRedundancy::createPSU(
}
}
}
+ checkRedundancyEvent();
},
"xyz.openbmc_project.ObjectMapper",
"/xyz/openbmc_project/object_mapper",
@@ -696,3 +730,117 @@ void ColdRedundancy::putWarmRedundant(void)
PowerSupply::~PowerSupply()
{
}
+
+void ColdRedundancy::checkRedundancyEvent()
+{
+ puRedundantTimer.expires_after(std::chrono::seconds(2));
+ puRedundantTimer.async_wait([this](const boost::system::error_code& ec) {
+ if (ec == boost::asio::error::operation_aborted)
+ {
+ return;
+ }
+
+ uint8_t psuWorkable = 0;
+ static uint8_t psuPreviousWorkable = numberOfPSU;
+
+ for (const auto& psu : powerSupplies)
+ {
+ if (psu->state == PSUState::normal)
+ {
+ psuWorkable++;
+ }
+ }
+
+ if (psuWorkable > psuPreviousWorkable)
+ {
+ if (psuWorkable > redundancyPSURequire)
+ {
+ if (psuWorkable == numberOfPSU)
+ {
+ // When all PSU are work correctly, it is full redundant
+ sd_journal_send(
+ "MESSAGE=%s", "Power Unit Full Redundancy Regained",
+ "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
+ "OpenBMC.0.1.PowerUnitRedundancyRegained", NULL);
+ }
+ else if (psuPreviousWorkable <= redundancyPSURequire)
+ {
+ // Not all PSU can work correctly but system still in
+ // redundancy mode and previous status is non redundant
+ sd_journal_send(
+ "MESSAGE=%s",
+ "Power Unit Redundancy Regained but not in Full "
+ "Redundancy",
+ "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
+ "OpenBMC.0.1.PowerUnitDegradedFromNonRedundant", NULL);
+ }
+ }
+ else if (psuPreviousWorkable == 0)
+ {
+ // Now system is not in redundancy mode but still some PSU are
+ // workable and previously there is no any workable PSU in the
+ // system
+ sd_journal_send(
+ "MESSAGE=%s",
+ "Power Unit Redundancy Sufficient from insufficient",
+ "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
+ "OpenBMC.0.1.PowerUnitNonRedundantFromInsufficient", NULL);
+ }
+ }
+ else if (psuWorkable < psuPreviousWorkable)
+ {
+ if (psuWorkable > redundancyPSURequire)
+ {
+ // One PSU is now not workable, but other workable PSU can still
+ // support redundancy mode.
+ sd_journal_send(
+ "MESSAGE=%s", "Power Unit Redundancy Degraded",
+ "PRIORITY=%i", LOG_WARNING, "REDFISH_MESSAGE_ID=%s",
+ "OpenBMC.0.1.PowerUnitRedundancyDegraded", NULL);
+
+ if (psuPreviousWorkable == numberOfPSU)
+ {
+ // One PSU become not workable and system was in full
+ // redundancy mode.
+ sd_journal_send(
+ "MESSAGE=%s",
+ "Power Unit Redundancy Degraded from Full Redundant",
+ "PRIORITY=%i", LOG_WARNING, "REDFISH_MESSAGE_ID=%s",
+ "OpenBMC.0.1.PowerUnitDegradedFromRedundant", NULL);
+ }
+ }
+ else
+ {
+ if (psuPreviousWorkable > redundancyPSURequire)
+ {
+ // No enough workable PSU to support redundancy and
+ // previously system is in redundancy mode.
+ sd_journal_send(
+ "MESSAGE=%s", "Power Unit Redundancy Lost",
+ "PRIORITY=%i", LOG_ERR, "REDFISH_MESSAGE_ID=%s",
+ "OpenBMC.0.1.PowerUnitRedundancyLost", NULL);
+ if (psuWorkable > 0)
+ {
+ // There still some workable PSU, but system is not
+ // in redundancy mode.
+ sd_journal_send(
+ "MESSAGE=%s",
+ "Power Unit Redundancy NonRedundant Sufficient",
+ "PRIORITY=%i", LOG_WARNING, "REDFISH_MESSAGE_ID=%s",
+ "OpenBMC.0.1.PowerUnitNonRedundantSufficient",
+ NULL);
+ }
+ }
+ if (psuWorkable == 0)
+ {
+ // No any workable PSU on the system.
+ sd_journal_send(
+ "MESSAGE=%s", "Power Unit Redundancy Insufficient",
+ "PRIORITY=%i", LOG_ERR, "REDFISH_MESSAGE_ID=%s",
+ "OpenBMC.0.1.PowerUnitNonRedundantInsufficient", NULL);
+ }
+ }
+ }
+ psuPreviousWorkable = psuWorkable;
+ });
+}