storage: add support for multiple storages
Updated Storage resource to `#Storage.v1_9_1.Storage` to support the
change.
Follow the Swordfish spec to setup the Storage relationship[1].
There will now be two Storage Collection `/redfish/v1/Stroage` and
`/redfish/v1/Systems/system/Storage`. The storage in `/Storage` will be
treated as a subsystem and only link to the `/Systems/system/Storage`
under `Links/StorageServices` resource.
The `/Storage` won't contain Drives or StorageControllers.
Tested:
Passed Redfish Validator for related resources.
```
*** /redfish/v1/Storage/storage_1
INFO - Type (Storage.v1_7_1.Storage), GET SUCCESS (time: 0)
WARNING - StorageControllers: The given property is deprecated: This property has been deprecated in favor of Controllers to allow for storage controllers to be represented as their own resources.
INFO - Attempt 1 of /redfish/v1/Chassis/chassis0/Drives/drive0
INFO - Response Time for GET to /redfish/v1/Chassis/chassis_0/Drives/drive_0: 0.07591272401623428 seconds.
INFO - PASS
INFO -
```
Chassis
```
wget -qO- http://localhost:80/redfish/v1/Chassis/chassis0
{
"@odata.id": "/redfish/v1/Chassis/chassis0",
"@odata.type": "#Chassis.v1_14_0.Chassis",
"Id": "chassis0",
"Links": {
"Storage": [
{
"@odata.id": "/redfish/v1/Systems/system/Storage/storage0"
}
],
"Storage@odata.count": 1
},
"Name": "chassis0",
}}
```
Storage Collection
```
wget -qO- http://localhost:80/redfish/v1/Storage
{
"@odata.id": "/redfish/v1/Storage",
"@odata.type": "#StorageCollection.StorageCollection",
"Members": [
{
"@odata.id": "/redfish/v1/Storage/storage0"
}
],
"Members@odata.count": 1,
"Name": "Storage Collection"
}
wget -qO- http://localhost:80/redfish/v1/Systems/system/Storage
{
"@odata.id": "/redfish/v1/Systems/system/Storage",
"@odata.type": "#StorageCollection.StorageCollection",
"Members": [
{
"@odata.id": "/redfish/v1/Systems/system/Storage/storage0"
}
],
"Members@odata.count": 1,
"Name": "Storage Collection"
}
```
Storage
```
wget -qO- http://localhost:80/redfish/v1/Storage/storage0
{
"@odata.id": "/redfish/v1/Storage/storage0",
"@odata.type": "#Storage.v1_9_1.Storage",
"Id": "storage0",
"Links": {
"StorageServices": [
{
"@odata.id": "/redfish/v1/Systems/system/Storage/storage0"
}
],
"StorageServices@odata.count": 1
},
"Name": "Storage",
"Status": {
"State": "Enabled"
}
}
wget -qO- http://localhost:80/redfish/v1/Systems/system/Storage/storage0
{
"@odata.id": "/redfish/v1/Systems/system/Storage/storage0",
"@odata.type": "#Storage.v1_9_1.Storage",
"Drives": [
{
"@odata.id": "/redfish/v1/Chassis/chassis0/Drives/drive0"
}
],
"Drives@odata.count": 1,
"Id": "storage0",
"Name": "Storage",[1]
"Status": {
"Health": "OK",
"HealthRollup": "OK",
"State": "Enabled"
},
"StorageControllers": [
{
"@odata.id": "/redfish/v1/Systems/system/Storage/storage0#/StorageControllers/0",
"@odata.type": "#Storage.v1_7_0.StorageController",
"MemberId": "controller",
"Name": "controller",
"Status": {
"Health": "OK",
"HealthRollup": "OK",
"State": "Enabled"
}
}
]
}
```
[1] https://www.snia.org/sites/default/files/technical-work/swordfish/draft/v1.2.2/pdf/Swordfish_v1.2.2_NVMeMappingGuide.pdf#page=17
Change-Id: Ib81b68e7f61b817d4dfa4ed2f27afd6e74e8ce58
Signed-off-by: Tom Tung <shes050117@gmail.com>
Signed-off-by: Willy Tu <wltu@google.com>
Signed-off-by: Ed Tanous <edtanous@google.com>
diff --git a/redfish-core/lib/chassis.hpp b/redfish-core/lib/chassis.hpp
index 6cb877f..8ac7caa 100644
--- a/redfish-core/lib/chassis.hpp
+++ b/redfish-core/lib/chassis.hpp
@@ -40,6 +40,54 @@
{
/**
+ * @brief Retrieves resources over dbus to link to the chassis
+ *
+ * @param[in] asyncResp - Shared pointer for completing asynchronous
+ * calls
+ * @param[in] path - Chassis dbus path to look for the storage.
+ *
+ * Calls the Association endpoints on the path + "/storage" and add the link of
+ * json["Links"]["Storage@odata.count"] =
+ * {"@odata.id", "/redfish/v1/Storage/" + resourceId}
+ *
+ * @return None.
+ */
+inline void getStorageLink(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const sdbusplus::message::object_path& path)
+{
+ sdbusplus::asio::getProperty<std::vector<std::string>>(
+ *crow::connections::systemBus, "xyz.openbmc_project.ObjectMapper",
+ (path / "storage").str, "xyz.openbmc_project.Association", "endpoints",
+ [asyncResp](const boost::system::error_code ec,
+ const std::vector<std::string>& storageList) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "getStorageLink got DBUS response error";
+ return;
+ }
+
+ nlohmann::json::array_t storages;
+ for (const std::string& storagePath : storageList)
+ {
+ std::string id =
+ sdbusplus::message::object_path(storagePath).filename();
+ if (id.empty())
+ {
+ continue;
+ }
+
+ nlohmann::json::object_t storage;
+ storage["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Systems/system/Storage/{}", id);
+ storages.emplace_back(std::move(storage));
+ }
+ asyncResp->res.jsonValue["Links"]["Storage@odata.count"] =
+ storages.size();
+ asyncResp->res.jsonValue["Links"]["Storage"] = std::move(storages);
+ });
+}
+
+/**
* @brief Retrieves chassis state properties over dbus
*
* @param[in] asyncResp - Shared pointer for completing asynchronous calls.
@@ -379,9 +427,9 @@
sdbusplus::asio::getAllProperties(
*crow::connections::systemBus, connectionName, path,
"xyz.openbmc_project.Inventory.Decorator.Asset",
- [asyncResp, chassisId(std::string(chassisId))](
- const boost::system::error_code& /*ec2*/,
- const dbus::utility::DBusPropertiesMap& propertiesList) {
+ [asyncResp, chassisId(std::string(chassisId)),
+ path](const boost::system::error_code& /*ec2*/,
+ const dbus::utility::DBusPropertiesMap& propertiesList) {
const std::string* partNumber = nullptr;
const std::string* serialNumber = nullptr;
const std::string* manufacturer = nullptr;
@@ -470,6 +518,7 @@
asyncResp->res.jsonValue["Links"]["ManagedBy"] =
std::move(managedBy);
getChassisState(asyncResp);
+ getStorageLink(asyncResp, path);
});
for (const auto& interface : interfaces2)