Update status in Redfish
Create associations when failed to change the
status to Warning.
Tested:
{
"@odata.context": "/redfish/v1/$metadata#Drive.Drive",
"@odata.id": "/redfish/v1/Systems/system/Storage/1/Drive/Drive_1",
"@odata.type": "#Drive.v1_7_0.Drive",
"Status": {
"Health": "Warning",
"HealthRollup": "Warning",
"State": "Enabled"
}
}
Change-Id: I3e5f87dc1253e8f24396a924e79d5474b0e5754a
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/hsbp-manager/include/utils.hpp b/hsbp-manager/include/utils.hpp
index 0b47a54..a3b0294 100644
--- a/hsbp-manager/include/utils.hpp
+++ b/hsbp-manager/include/utils.hpp
@@ -71,6 +71,12 @@
const static constexpr char* property = "CurrentHostState";
} // namespace power
+namespace association
+{
+const static constexpr char* interface =
+ "xyz.openbmc_project.Association.Definitions";
+} // namespace association
+
namespace hsbp
{
enum class registers : uint8_t
diff --git a/hsbp-manager/src/hsbp_manager.cpp b/hsbp-manager/src/hsbp_manager.cpp
index f25f266..d65d80c 100644
--- a/hsbp-manager/src/hsbp_manager.cpp
+++ b/hsbp-manager/src/hsbp_manager.cpp
@@ -145,9 +145,10 @@
struct Drive
{
- Drive(size_t driveIndex, bool isPresent, bool isOperational, bool nvme,
+ Drive(size_t driveIndex, bool present, bool isOperational, bool nvme,
bool rebuilding) :
- isNvme(nvme)
+ isNvme(nvme),
+ isPresent(present)
{
constexpr const char* basePath =
"/xyz/openbmc_project/inventory/item/drive/Drive_";
@@ -160,7 +161,28 @@
operationalIface = objServer.add_interface(
itemIface->get_object_path(),
"xyz.openbmc_project.State.Decorator.OperationalStatus");
- operationalIface->register_property("Functional", isOperational);
+
+ operationalIface->register_property(
+ "Functional", isOperational,
+ [this](const bool req, bool& property) {
+ if (!isPresent)
+ {
+ return 0;
+ }
+ if (property == req)
+ {
+ return 1;
+ }
+ property = req;
+ if (req)
+ {
+ clearFailed();
+ return 1;
+ }
+ markFailed();
+ return 1;
+ });
+
operationalIface->initialize();
rebuildingIface = objServer.add_interface(
itemIface->get_object_path(), "xyz.openbmc_project.State.Drive");
@@ -170,6 +192,16 @@
objServer.add_interface(itemIface->get_object_path(),
"xyz.openbmc_project.Inventory.Item.Drive");
driveIface->initialize();
+ associations = objServer.add_interface(itemIface->get_object_path(),
+ association::interface);
+ associations->register_property("Associations",
+ std::vector<Association>{});
+ associations->initialize();
+
+ if (isPresent && (!isOperational || rebuilding))
+ {
+ markFailed();
+ }
}
virtual ~Drive()
{
@@ -178,6 +210,7 @@
objServer.remove_interface(rebuildingIface);
objServer.remove_interface(assetIface);
objServer.remove_interface(driveIface);
+ objServer.remove_interface(associations);
}
void createAsset(
@@ -197,13 +230,38 @@
assetIface->initialize();
}
+ void markFailed(void)
+ {
+ // todo: maybe look this up via mapper
+ constexpr const char* globalInventoryPath =
+ "/xyz/openbmc_project/CallbackManager";
+
+ if (!isPresent)
+ {
+ return;
+ }
+
+ operationalIface->set_property("Functional", false);
+ std::vector<Association> warning = {
+ {"", "warning", globalInventoryPath}};
+ associations->set_property("Associations", warning);
+ }
+
+ void clearFailed(void)
+ {
+ operationalIface->set_property("Functional", true);
+ associations->set_property("Associations", std::vector<Association>{});
+ }
+
std::shared_ptr<sdbusplus::asio::dbus_interface> itemIface;
std::shared_ptr<sdbusplus::asio::dbus_interface> operationalIface;
std::shared_ptr<sdbusplus::asio::dbus_interface> rebuildingIface;
std::shared_ptr<sdbusplus::asio::dbus_interface> assetIface;
std::shared_ptr<sdbusplus::asio::dbus_interface> driveIface;
+ std::shared_ptr<sdbusplus::asio::dbus_interface> associations;
bool isNvme;
+ bool isPresent;
};
struct Backplane
@@ -337,18 +395,27 @@
{
uint8_t nvme = ifdet ^ presence;
- for (size_t ii = 0; ii < maxDrives; ii++)
+ size_t ii = 0;
+
+ for (auto it = drives.begin(); it != drives.end(); it++, ii++)
{
bool isNvme = nvme & (1 << ii);
bool isPresent = isNvme || (presence & (1 << ii));
bool isFailed = !isPresent || (failed & (1 << ii));
bool isRebuilding = isPresent && (rebuilding & (1 << ii));
- Drive& drive = drives[ii];
- drive.isNvme = isNvme;
- drive.itemIface->set_property("Present", isPresent);
- drive.operationalIface->set_property("Functional", !isFailed);
- drive.rebuildingIface->set_property("Rebuilding", isRebuilding);
+ it->isNvme = isNvme;
+ it->itemIface->set_property("Present", isPresent);
+ it->isPresent = isPresent;
+ it->rebuildingIface->set_property("Rebuilding", isRebuilding);
+ if (isFailed || isRebuilding)
+ {
+ it->markFailed();
+ }
+ else
+ {
+ it->clearFailed();
+ }
}
}
@@ -508,13 +575,13 @@
std::shared_ptr<sdbusplus::asio::dbus_interface> hsbpItemIface;
std::shared_ptr<sdbusplus::asio::dbus_interface> versionIface;
- std::vector<Drive> drives;
+ std::list<Drive> drives;
std::vector<std::shared_ptr<Led>> leds;
std::shared_ptr<boost::container::flat_set<Mux>> muxes;
};
std::unordered_map<std::string, Backplane> backplanes;
-std::vector<Drive> ownerlessDrives; // drives without a backplane
+std::list<Drive> ownerlessDrives; // drives without a backplane
static size_t getDriveCount()
{
@@ -695,9 +762,10 @@
<< " " << driveIndex << "\n";
return;
}
+ auto it = parent->drives.begin();
+ std::advance(it, driveIndex);
- Drive& drive = parent->drives[driveIndex];
- drive.createAsset(assetInventory);
+ it->createAsset(assetInventory);
},
owner, path, "org.freedesktop.DBus.Properties", "GetAll",
"" /*all interface items*/);
@@ -925,6 +993,10 @@
});
});
+ auto iface =
+ objServer.add_interface("/xyz/openbmc_project/inventory/item/storage",
+ "xyz.openbmc_project.inventory.item.storage");
+
io.post([]() { populate(); });
setupPowerMatch(conn);
io.run();